JS: prototype chain, __proto__, prototype

Often, I don't understand prototypes, __proto__ and prototype, so I will learn a little bit today.

Both prototype and __proto__ point to the prototype object.

__proto__: Object properties . Every object has.

prototype: Function -specific properties.

let obj = {};
console.log('__proto__' in obj); // true
console.log('prototype' in obj); // false

const fun = function () {};
console.log('__proto__' in fun); // true
console.log('prototype' in fun); // true

 Not all Function objects have a prototype property. Typical is an arrow function.

const fn = () => {};
console.log('prototype' in fn);             // false

const method = ({foo () {}}).foo;
console.log('prototype' in method);         // false

async function asyncFunction() {}
console.log('prototype' in asyncFunction);  // false

The __proto__ attribute of an object returns the prototype of the object.

By default, the prototype property of a function points to an object. For ordinary functions, this attribute is basically useless. For the constructor, when an instance is generated, this attribute will automatically become the prototype of the instance object.

let obj = {};
console.log(obj.__proto__ === Object.prototype); // true

const f = function () {}
console.log(f.__proto__ === Function.prototype); // true

const F = function () {};
console.log((new F()).__proto__ === F.prototype); // true

prototype property

effect:

The design idea of ​​the JavaScript inheritance mechanism is that all properties and methods of the prototype object can be shared by the instance object.

The prototype attribute of the constructor is used to define the properties and methods shared by all instance objects.

const Cat = function (name) {
  this.name = name;
}
Cat.prototype.host = '张三';
Cat.prototype.aowu = function () {
  return this.name + ': 嗷呜';
}
let nuomi = new Cat('糯米');
let tangyuan = new Cat('汤圆');
console.log(nuomi.aowu === tangyuan.aowu); // true
console.log(nuomi.host);                   // '张三'
console.log(tangyuan.host);                // '张三'

When the instance object itself does not have a certain property or method, it will go to the prototype object to find the property or method.

When the instance object itself     has a certain property or method, it will not go to the prototype object to find this property or method.

tangyuan.host = '李四';
console.log(nuomi.host);     // '张三'
console.log(tangyuan.host);  // '李四'

constructor property

By default, the prototype object has a constructor attribute, which points to the constructor of the prototype object by default.

const Cat = function (name) {}
console.log(Cat.prototype.constructor === Cat); // true

let nuomi = new Cat('糯米');
console.log(nuomi.constructor === Cat);             // true
console.log(nuomi.hasOwnProperty('constructor'));   // false

Nuomi is an instance object of the constructor Cat, but nuomi itself does not have a constructor attribute, which actually reads the Cat.prototype.constructor attribute on the prototype chain.

After introducing the prototype, continue with the prototype chain.

prototype chain

As mentioned above, for a constructor, when an instance is generated, the prototype attribute will automatically become the prototype of the instance object.

That is: instance object.__proto__ === constructor.prototype.

First, we define the constructor F and use it to generate an instance object f. f.__proto__ points to the prototype property of the constructor F. Right now:

function F() {}
const f = new F();
console.log(f.__proto__ === F.prototype); // true

The constructor F is an instance of Function, so F.__proto__ points to the prototype property of Function.

console.log(F.__proto__ === Function.prototype); // true

By default, the prototype property of a function points to an object, that is, the prototype property of a function is an instance of Object.

The __proto__ of function.prototype points to Object.prototype.
So, both F.prototype.__proto__ and Function.prototype.__proto__ point to Object.prototype.

console.log(F.prototype.__proto__ === Object.prototype);        // true
console.log(Function.prototype.__proto__ === Object.prototype); // true

However, except for Function.prototype, the data type of function.prototype is 'object'

console.log(typeof Function.prototype); // 'function'
console.log(typeof Object.prototype);   // 'object'
console.log(typeof F.prototype);        // 'object'
console.log(typeof Date.prototype);     // 'object'

Functions (including constructors, built-in function objects (Function, Object, etc.)) are instances of Function. So Function.__proto__ points to Function.prototype, so it will not be so difficult to understand.

console.log(Function.__proto__ === Function.prototype);  // true
console.log(Object.__proto__ === Function.prototype);    // true
console.log(Array.__proto__ === Function.prototype);     // true
console.log(Date.__proto__ === Function.prototype);      // true
console.log(RegExp.__proto__ === Function.prototype);    // true
console.log(Error.__proto__ === Function.prototype);     // true
console.log(Number.__proto__ === Function.prototype);    // true
console.log(String.__proto__ === Function.prototype);    // true
console.log(Boolean.__proto__ === Function.prototype);   // true

Special attention needs to be paid to Math, which is not a constructor. All properties and methods are called on the Math object.

console.log(Math.__proto__ === Object.prototype); // true

JavaScript stipulates that all objects have their own prototype object (prototype). On the one hand, any object can serve as the prototype of other objects; on the other hand, since the prototype object is also an object, it also has its own prototype. Therefore, a "prototype chain" (prototype chain) will be formed: object to prototype, and then to the prototype of the prototype...

In JavaScript, everything is an object! If traced up layer by layer, the prototypes of all objects can be traced back to Object.prototype eventually . That is, all objects inherit the properties of Object.prototype.

What about the prototype of Object.prototype? is null. null has no properties or methods, nor does it have a prototype of its own. Therefore, the end of the prototype chain is null.

console.log(Object.prototype.__proto__ === null); // true

Another: __proto__ is not a standard attribute (the fifth edition of ECMA-262 calls the attribute or pointer [[Prototype]]), only the browser needs to deploy, and other environments may not have this attribute.

Therefore, this attribute should be used as little as possible, but Object.getPrototypeOf() and Object.setPrototypeOf() should be used to read and write prototype objects.

So far, the relevant knowledge of the prototype chain has basically been sorted out. In summary, the map of the prototype chain can be drawn.

at last:

instanceof operator: The operator returns a Boolean value indicating whether the object is an instance of a constructor. The left side of the operator is the instance object, and the right side is the constructor. The principle is to check whether the prototype property of the constructor on the right is on the prototype chain of the object on the left .

Object.prototype.isPrototypeOf(): Used to determine whether the object is the prototype of the parameter object.

function F() {}
const f = new F();
console.log(f instanceof F);                    // true
console.log(f instanceof Object);               // true
console.log(F.prototype.isPrototypeOf(f));      // true
console.log(Object.prototype.isPrototypeOf(f)); // true

// 一种特殊情况,判断失真
let obj = Object.create(null);
console.log(typeof obj);                             // 'object'
console.log(obj instanceof Object);                  // false
console.log(Object.prototype.isPrototypeOf(obj));    // false

The end.

Guess you like

Origin blog.csdn.net/weixin_43932309/article/details/130045017