7

foreword

When other programming languages such as Java use the new command, the constructor of the " class " will be called. However, JavaScript does not have a " class " and itself does not provide a class implementation (although the class keyword is provided in ES6, it is just syntactic sugar, and JavaScript is still prototype-based ). So, JavaScript made a simplified idea, new command is not followed by a class, but a constructor. The constructor is used to generate an instance object, but its disadvantage is that it cannot share properties and methods. Therefore, a prototype property is set for the constructor, which contains an object ( prototype object). All properties and methods that need to be shared by instance objects are placed in this object, and those properties and methods that do not need to be shared are placed in the constructor.

💡Warm reminder: The full text of this article 1986 words, the recommended reading time is 10m , come on, old iron!

1. Explicit prototype (prototype)

1.1 Introduction

Each function will have a property named prototype after it is created:

 function Parent() {

}
Parent.prototype.name = 'kite';
let child = new Parent();
console.log(child.name);

This attribute points to the prototype object of the function (the function constructed by the Function.prototype.bind method is an exception, it does not have the prototype attribute), that is, the prototype of the instance created by calling the constructor, that is, in the example The prototype of the child.

What is a prototype: Every JavaScript object (except null ) is associated with another object, which is the prototype, and as mentioned above, each object "inherits properties" from the prototype.

Prototypes indicate the relationship between constructors and instance prototypes .

1.2 Function

Explicit prototypes are used to implement prototype-based inheritance and property sharing.

2. Implicit prototype (__proto__)

2.1 Introduction

Any object in JS has a built-in property [[prototype]], there is no standard way to access it before ES5, most browsers access it through __proto__ . ES5中有了对这个内置属性标准的get方法: Object.getPrototypeOfObject.prototype是个例外, __proto__ null )。

 function Parent() {

}
let child = new Parent();
console.log(child.__proto__ === Parent.prototype); // true

2.2 Function

Implicit prototypes form the prototype chain and are also used to implement prototype-based inheritance. for example:
When we access a property in the object, if we can't find it in the object, we will always search along __proto__ (the prototype of the prototype) until we find the topmost level.

 function Parent() {

}
Parent.prototype.name = 'dave';
let child = new Parent();
child.name = 'kite';
console.log(child.name); // 'kite'
delete child.name;
console.log(child.name); // 'dave'

In the above example, add the name attribute to the object child , when accessing the name attribute, the attribute value kite of the object itself is found. After deleting name attribute, visit the name attribute again, if the attribute is not found in the object, then look for it in the prototype, and find dave . Assuming that the attribute is not found in the prototype, it will go to the prototype of the prototype to find it.

We know that the prototype is an object, and since it is an object, it can be created in the most primitive way:

 let obj = new Object();

Prototypes are generated by Object constructing objects. Then what is the prototype of Object.prototype ?

 Object.prototype.__proto__ = null; // true

null indicates that there is no object, indicating that the search can be stopped here.

2.3 Point to

__proto__ points to the explicit prototype of the function that created the object, the key is to find the constructor that created the object. There are three forms of creating objects: object literals; new ( class ); ES5 Object.create() . There is only one essence new .

2.3.1 Object Literals

 let obj = {
    name: 'ctt'
}

The object declared by the object literal inherits from Object , which is the same as new Object , and its prototype is
Object.prototype . And Object.prototype does not inherit any properties and methods.

2.3.2 new

An object created using a constructor function inherits its properties from the constructor function.
Specifically, it is divided into the following situations:

  1. 内建对象<br>如Array()Array.prototypeArray.prototype为一个对象,这个对象由---f5c14fc2143d70c4dcf574be2688e945 Object()函数create. So, Array.prototype.__proto__ === Object.prototype , the prototype chain is: Array.prototype -> Object.prototype -> null .
  2. custom object
  3. by default:

     function Foo() {};
    let foo = new Foo();
    Foo.prototype.__proto__ === Object.prototype;
  • Other cases:

     // 想让Foo继承Bar
    function Bar() {
    }
    Foo.prototype = new Bar();
    Foo.prototype.__prototype__ = Bar.prototype;
    // 重新定义Foo.prototype
    Foo.prototype = {
      a: 1,
      b: 2
    };
    Foo.prototype.__proto__ = Object.prototype;

The above two cases have been rewritten Foo.prototype , so Foo.prototype.constructor is changed, constructor and the original constructor Foo cut off.

  1. Constructor <br>Constructor is an instance of Function() , so the implicit prototype of the constructor points to
    Function.prototype . The engine created Object.prototype and then created
    Function.prototype , linking the two by __proto__ .

Function.prototype === Function.__proto__ ,其他所有的构造函数都可以通过原型链找到Function.prototypefunction Function()一个函数,为了不产生混乱, function Function The __proto__ in touch with Function.prototype on.

2.3.3 class

In ES5, each object has a __proto__ attribute, pointing to the prototype attribute of the corresponding constructor, and class as syntactic sugar for the constructor, and has prototype attribute and __proto__ attribute, so there are two inheritance chains at the same time.

  • The subclass __proto__ indicates the inheritance of the constructor, which always points to the parent class;
  • Subclass prototype attribute __proto__ represents method inheritance, always pointing to parent class
    prototype .
 class Parent {

}
class Child extends Parent {

}
Child.__proto__ === Parent;
Child.prototype.__proto__ === Parent.prototype;

作为一个对象,子类Child__proto__ )是父类Parent ;作为一个构造函数,子类的原型对象( prototype ) is an instance of the parent class prototype object ( prototype ).

2.3.4 Object.create()

Object.create() is an ES5 method that can be called to create a new object. The prototype of the new object is the first parameter passed in.

Third, the constructor (constructor)

The above shows that both the constructor and the instance can point to the prototype. The next attribute is to let the prototype point to the constructor (there is no attribute pointing to the instance, because the constructor can generate multiple instances), it is constructor properties, each prototype has a constructor attribute that points to the constructor.

 function Parent() {

}
console.log(Parent === Parent.prototype.constructor);

The various relationships about the prototype are summarized as follows:
6C8EFCFC-52BD-44DA-BE78-7F7D277DF9FA.png

Fourth, the difference between this and prototype definition methods

  1. Using the method implemented by this , you can access private variables and private methods in the class. The methods implemented by the prototype object cannot access the private variables and methods in the class.
  2. When an instance accesses a property or method of an object, it will follow the rules of searching the prototype chain prototype chain . First, look for its own static properties and methods, then find the accessible properties and methods of the construction context, and finally find the prototype chain of the construction.
  3. Another difference between the definitions of this and prototype is that they occupy different space in memory. Using the "this" keyword, when the instance is initialized, all properties, methods and required space included in the construction method are opened up for each instance, and the use of prototype Definition, because prototype actual is a reference to the parent, so it saves resources on initialization and storage than "this".

V. Summary

  1. After each function is created, there will be an attribute named prototype , this attribute points to the prototype object (explicit prototype) of the function, and all the attributes and methods that need to be shared by instance objects are placed in this object;
  2. Any object has a built-in property __proto__ pointing to the explicit prototype of the function that created the object;
  3. class 作为构造函数的语法糖, prototype __proto__ ,作为一个对象,子类Child的原型( __proto__ ) is the parent class Parent ; as a constructor, the prototype object of the subclass ( prototype prototype ).
  4. Each prototype has a constructor attribute that points to the constructor, ie Parent === Parent.prototype.constructor

refer to

JavaScript - Prototypes, Prototype Chains · Issue #13 · cttin/cttin.github.io · GitHub


云鱼
3.2k 声望530 粉丝

感谢阅读、浏览和关注!