Understand prototype and prototype chain

prospect

JavaScriptIt's object-oriented programming, but it's different from other programming languagesJavaScriptObject-oriented is not dependent on abstract classes, but through prototype chains. stayC++andJavaUsenewCommand, will be called"class"Constructor for. While inJavascriptIn language,newThe command is not followed by a class, but by a constructor. However, one disadvantage of using constructors to generate instance objects is that they cannot share properties and methods. To solve this problem, set theprototypeProperty, that is, prototype.

Starting from a constructor

One disadvantage of using constructors to generate instance objects is that they cannot share properties and methods. This will result in the waste of system resources. Specific examples are as follows:

function Cat(name, color) {
  this.name = name;
  this.color = color;
  this.meow = function () {
    console.log('Meow meow');
  };
}

var cat1 = new Cat('Big wool', 'white');
var cat2 = new Cat('20 Fen', 'black');

cat1.meow === cat2.meow
// false

From the above code, we can see that the meow methods of cat1 and cat2 are independent but the functions implemented are the same, which is unnecessary and wasteful of system resources, because all meow methods are the same behavior and should be shared completely. The solution to this problem is to add the prototype property to the JavaScript constructor.

What is prototype?

Only functions have the prototype property, also known as the explicit prototype. The prototype property contains an object. All the properties and methods that need to be shared by instance objects are placed in this object. Those properties and methods that do not need to be shared are placed in the constructor.

According to JavaScript, each function has a prototype attribute that points to an object.

function f() {}
typeof f.prototype // "object"

This property is basically useless for ordinary functions. However, for constructors, when an instance is generated, this property automatically becomes the prototype of the instance object.

function Animal(name) {
  this.name = name;
}
Animal.prototype.color = 'white';

var cat1 = new Animal('Big wool');
var cat2 = new Animal('20 Fen');

cat1.color // 'white'
cat2.color // 'white'

In the above code, the prototype property of the constructor Animal is the prototype object of the instance objects cat1 and cat2. A color attribute is added to the prototype object. As a result, all instance objects share this attribute.

The properties of the prototype object are not the properties of the instance object itself. As long as the prototype object is modified, the change is immediately reflected in all instance objects

Animal.prototype.color = 'yellow';

cat1.color // "yellow"
cat2.color // "yellow"

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

cat1.color = 'black';

cat1.color // 'black'
cat2.color // 'yellow'
Animal.prototype.color // 'yellow';

In summary, the role of prototype objects is to define the properties and methods shared by all instance objects. That's why it's called a prototype object, and an instance object can be seen as a child object derived from the prototype object.

Note: in Object.prototype, Object is a global Object, also a constructor, and other basic types of global objects are also constructors.

_What's proto?

_Proto UU is an attribute of every object, also known as implicit prototype. However, the "proto" is not a standard attribute, but it is implemented by some browsers. The corresponding standard attribute is [[peotype]].

In most cases, the "proto" can be understood as the "prototype of a constructor". It is the link established between an instance and its constructor, that is, the "proto" = = constructor. Prototype "

Example:

// Literal measure
var a = {};
console.log(a.prototype);  //undefined
console.log(a.__proto__);  //Object {}

//Constructor mode
var b = function(){}
console.log(b.prototype);  //b {}
console.log(b.__proto__);  //function() {}

// Object.create method
var a1 = {}
var a2 = Object.create(a1)
console.log(b.prototype);  //undefined
console.log(b.__proto__);  //Object a1

Suggestions for using "proto" in ES6

This paragraph is excerpt from Introduction to Ruan Yifeng ES6 For details, click view.

1. The "proto" attribute is not written to the body of ES6, but to the appendix,

2. The reason is that the double underscores before and after \\\\\\\\\\\\.

3. The standard clearly stipulates that only the browser must deploy this attribute, and other running environments do not need to deploy, and the new code is better to think that this attribute does not exist.

4. Do not use this property from the semantic point of view or from the compatibility point of view. Instead, use the following Object.setPrototypeOf() (write operation), Object.getPrototypeOf() (read operation), and Object.create() (generate operation).

What is a prototype chain?

Each object initializes a property inside it, that is, prototype. When we access the property of an object, if the property does not exist inside the object, then it will go to prototype to find the property, and the prototype will have its own prototype, so we have been looking for it, that is, the concept of prototype chain.

End of prototype chain

All object prototypes can be traced back to Object.prototype. Does Object.prototype object have its prototype? The answer is that the prototype of Object.prototype is null. Null does not have any properties or methods, nor does it have its own prototype. Therefore, the end of the prototype chain is null.

1. End of string prototype chain

let test = 'hello'

// String prototype
let stringPrototype = Object.getPrototype(test) 

// The prototype of a String is a String object
stringPrototype === String.Prototype  // true 

// The prototype of a String Object is an Object object Object
Object.getPrototypeOf(stringPrototype) === Object.prototype // true 

2. End point of function principle chain


let test = function () {}
let fnPrototype = Object.getPrototype(test)
fnPrototype === Function.prototype // true
Object.getPrototypeOf(Function.prototype) === Object.Prototype // true

What are prototype chains used for?

1. Attribute search

When the JS engine looks up the property of an object, it first looks up whether the property exists in the object itself. If it does not, it will go to the prototype chain to find it, but it will not find its prototype.

Let's use an example to illustrate:

let test = 'hello'

// String prototype
let stringPrototype = Object.getPrototype(test) 

// The prototype of a String is a String object
stringPrototype === String.Prototype  // true 

// The prototype of a String Object is an Object object Object
Object.getPrototypeOf(stringPrototype) === Object.prototype // true 

2. Refuse to find the prototype chain

hasOwnPrototype: indicates whether the object has the specified attribute in its own attribute.

Syntax: obj.hasOwnPrototype(prop).

Parameter prop: the property to find.

Return value: Boolean to determine whether it exists.

let test = {'ABC': 'EDF' }
test.hasOwnPrototype('ABC') // true
test.hasOwnPrototype('toString') // false

This method is on Object.prototype, which can be used by all objects and ignores the properties inherited from the prototype chain.

extend

constructor property

The prototype object has a constructor property, which by default points to the constructor where the prototype object is located.

function P() {}
P.prototype.constructor === P // true

Since the constructor property is defined on the prototype object, it means that it can be inherited by all instance objects.

function P() {}
var p = new P();

p.constructor === P // true
p.constructor === P.prototype.constructor // true
p.hasOwnProperty('constructor') // false

In the above code, P is the instance object of the constructor P, but P does not have the constructor property, which actually reads the P.prototype.constructor property on the prototype chain.

The function of constructor property

The constructor property is used to know which constructor generated an instance object.

Here's a little Chestnut:

function F() {};
var f = new F();

f.constructor === F // true
f.constructor === RegExp // false

On the other hand, with the constructor property, you can create another instance from one instance object.

Let me give you a little Chestnut:

function Constr() {}
var x = new Constr();

var y = new x.constructor();
y instanceof Constr // true

summary

There is no difficulty in the world, just afraid of the intentional people. Prototype and prototype chain are the development basis of front-end engineers. Although prototype is not easy to understand, I believe that it is not as difficult as expected as long as you are willing to learn and practice. I hope that this article will help my own group, and children's shoes will have some harvest after reading it.

Keywords: Javascript Attribute Programming

Added by SiMiE on Mon, 04 Nov 2019 11:08:48 +0200