Types in JS

There are seven primitive types and Object in js

  • undefined
  • boolean
  • number
  • string
  • bigint
  • symbol
  • null

Primitive types

number is a value in double-precision 64-bit binary format (-(253 -1) to 253 -1) based on the IEEE 754 standard. It does not give a specific type for integers. In addition to the ability to represent floating-point numbers, there are also signed values: +Infinity, -Infinity and NaN (Not-a-Number).

bigint can represent integers with arbitrary precision. When converting a bigint to a boolean, it behaves like a number. A bigint cannot be interchanged with a number. Otherwise, a TypeError will be thrown.

Both bigint and symbol are new to es2015 and are less commonly encountered. symbol can be simply but loosely analogized to the C enumeration type.

Difference between basic string and string object

Please note the distinction between JavaScript string objects and basic string values. (This is also true for Boolean and Numbers.)

String literals (defined by single or double quotes) and strings that call the String method directly (without generating a string object instance by new) are both basic strings.

JavaScript automatically converts the base string to a string object, and the methods of the string object can be used only after the base string has been converted to a string object.

When a basic string needs to call a method or query that is only available in a string object (which the basic string does not have), JavaScript automatically converts the basic string to a string object and calls the corresponding method or executes the query.

See https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String

Object

Object is a reference type. Most of the time assignments of reference types are shallow copies, such as this. To make a complete copy of an object, a deep copy is required (this is a topic for a separate article).

1
2
3
4
5
// 引用数据类型赋值
var a = {name: '张三'};
var b = a;
console.log(a); // {name: "张三"}
console.log(b); // {name: "张三"}

Functions are Object, arrays are Object, and can be simply but loosely interpreted as being Object except for the primitive type.

null and undefined

  • A variable that has been declared and not assigned is undefined
  • Using an undeclared variable directly will throw an error.
  • You can also assign undefined directly to a variable
  • null is usually a deliberate assignment or the end of a prototype chain
  • both null and undefined are false when converted to boolean values
  • null converts to 0 when converting to the data type number
  • undefined is converted to NaN when converting to the data type number
  • undefined is returned when trying to access a property that does not exist for the object

NaN is a special value, but in es2015, NaN is an attribute of Number. NaN is best used only to determine whether a variable is a number or not.

Type detection

typeof can only detect primitive data types. Arrays, objects, and the like all return object. But null also returns object. But the function returns function.

I think the safest way to detect the type is Object.prototype.toString.call(variable)

Objects and functions

Objects

Classification of objects.

  1. Built-in objects
    • objects defined by the es standard, which can be used in any es environment, e.g. Object Function Math Date, etc.
  2. Hosted objects
    • objects provided by the js runtime environment, such as objects provided by the browser: BOM (Browser Object Model) DOM (Document Object Model)
  3. Custom objects
    • Objects created by the developer

Every object in js has a prototype. The prototype of an object is also an object. An object inherits the properties and methods of the prototype. The object overrides the properties and methods of the prototype by the same name. All prototypes of objects eventually point to Object.prototype. The prototype of Object.prototype is null. The prototype can be accessed via the __proto__ property or Object.getPrototypeOf().

Functions

A function can be understood as a variable. The type of a function is Object. A syntax error is raised when the function name and the variable name are the same.

1
2
3
4
// 一个函数的声明
function a(){};
// 也可以写成这样
var a = function(){};

Functions have a property named prototype, and the value of this property is an object. This object will be called the prototype object of the function. The prototype object will have an attribute called constructor, which will point to the function itself.

prototype and __proto__ are not the same. prototype is only available to functions, __proto__ is available to all objects. Functions also have the __proto__ attribute.

The prototype of all functions will eventually point to Function.prototype. The prototype of Function.prototype is Object.prototype. The prototype of Object.prototype is null.

Function’s prototype and __proto__ are equivalent.

1
console.log(Object.is(Object.getPrototypeOf(Function), Function.prototype)); // true

new operator

The new keyword performs the following operations.

  1. creates an empty simple JavaScript object (i.e. {}).
  2. adds the attribute __proto__ to the newly created object from step 1, linking the attribute to the prototype object of the constructor.
  3. use the newly created object from step 1 as the context for this.
  4. if the function does not return an object, return this.

Example

1
2
3
4
5
6
7
8
(function(){
    let a = function(){};
    let b = new a();
    console.log(Object.is(b.__proto__, a.prototype)); // true;
    console.log(Object.is(a, a.prototype.constructor)); // true;
    console.log(Object.is(a.__proto__, Function.prototype)); // true;
    console.log(Object.is(Function.prototype.__proto__, Object.prototype)); // true;
})();

According to the above example, a will be called a constructor and b will be called an instance of a. A is essentially just a normal function, but when the new operator is used to create a new object b, a can be referred to as a constructor. In some contexts a will also be referred to as a class.

See https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/new

Prototype chain

Need to focus on these three attributes

  • prototype
    • This attribute is only available to functions
    • It points to the prototype object of the function
  • constructor
    • This attribute is only available to the function’s prototype object
    • refers to the function itself
  • __proto__
    • This attribute is available to all objects
    • refers to the object’s prototype

When accessing an object’s properties, it looks for its own properties first, and if not, it looks up the prototype’s properties one level at a time. Attempts to access a property that does not exist for the object will traverse the entire prototype chain.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@startuml
(null)
(Object.prototype)
(Function.prototype)
(Array.prototype)
(function Function) as funFunction
(function Object) as funObject
(function Array)as funArray
(function Example)as funExample
(Example.prototype)
(exampleObj)
(exampleArr)
(var obj = new Object<U+0028><U+0029>) as obj1
(var fun = new Function<U+0028><U+0029>) as fun1

Object.prototype --> null : "<U+005F>_proto__"
Function.prototype --> Object.prototype : "<U+005F>_proto__"
Example.prototype --> Object.prototype : "<U+005F>_proto__"
Array.prototype --> Object.prototype : "<U+005F>_proto__"
funFunction --> Function.prototype : "<U+005F>_proto__"
funObject --> funFunction : "<U+005F>_proto__"
funArray --> funFunction : "<U+005F>_proto__"
funExample --> funFunction : "<U+005F>_proto__"
exampleObj --> Example.prototype : "<U+005F>_proto__"
exampleArr --> Array.prototype : "<U+005F>_proto__"
obj1 --> Object.prototype : "<U+005F>_proto__"
fun1 --> Function.prototype : "<U+005F>_proto__"

funArray --> Array.prototype : "prototype"
funExample --> Example.prototype : "prototype"
funFunction --> Function.prototype : "prototype"
funObject --> Object.prototype : "prototype"

Array.prototype --> funArray : "constructor"
Example.prototype --> funExample : "constructor"
Function.prototype --> funFunction : "constructor"
Object.prototype --> funObject : "constructor"
@enduml

js prototype chain

In this diagram, function Excemple is a custom function. function Array is a built-in function of js.

The difference between in and hasOwnProperty

  • Both are used to determine if a property exists on an object.
  • hasOwnProperty can only determine if a property belongs to itself, it doesn’t look for properties in the prototype chain.
  • in can find properties in the prototype chain

Example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
(function(){
    let Person = function() {};
    Person.prototype.lastName = "Deng";
    let person = new Person();
    person.age = 12;
    console.log(person.hasOwnProperty('lastName')); // false
    console.log(person.hasOwnProperty('age')); // true
    console.log('lastName' in person); // true
    console.log('age' in person); // true
})()

getPrototypeOf and proto

__proto__ is a deprecated property https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/proto

The standard is to use the Object.getPrototypeOf() method instead of __proto__.

Other

A native prototype should not be extended unless it is intended to be compatible with new JavaScript features.

It is not recommended to redefine prototypes and not to redefine the prototype property of functions.

Object data output directly via console.log is always a little different than expected. This is probably why es2015 requires the Object.getPrototypeOf() method to get the object prototype instead of the __proto__ property.

js is a function-first programming language, where functions can be used as variables, parameters, and return values. js is also an object-oriented programming language, but unlike Java C++, js does not distinguish between classes and objects. js has only objects and uses a prototype chain approach to object inheritance.

The class is just syntactic sugar for the prototype chain.

In addition to prototype chains js has many syntactic pitfalls, such as this, closures, event loops, and IIFE.