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 article1986
words, the recommended reading time is10m
, 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.getPrototypeOf
( Object.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:
- 内建对象<br>如
Array()
,Array.prototype
,Array.prototype
为一个对象,这个对象由---f5c14fc2143d70c4dcf574be2688e945Object()
函数create. So,Array.prototype.__proto__ === Object.prototype
, the prototype chain is:Array.prototype -> Object.prototype -> null
. - custom object
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.
- Constructor <br>Constructor is an instance of
Function()
, so the implicit prototype of the constructor points to
Function.prototype
. The engine createdObject.prototype
and then created
Function.prototype
, linking the two by__proto__
.
Function.prototype === Function.__proto__
,其他所有的构造函数都可以通过原型链找到Function.prototype
, function 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:
Fourth, the difference between this and prototype definition methods
- 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. - 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. - Another difference between the definitions of
this
andprototype
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 ofprototype
Definition, becauseprototype
actual is a reference to the parent, so it saves resources on initialization and storage than "this".
V. Summary
- 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; - Any object has a built-in property
__proto__
pointing to the explicit prototype of the function that created the object; - class 作为构造函数的语法糖,
prototype
__proto__
,作为一个对象,子类Child
的原型(__proto__
) is the parent classParent
; as a constructor, the prototype object of the subclass (prototype
prototype
). - Each prototype has a
constructor
attribute that points to the constructor, ieParent === Parent.prototype.constructor
refer to
JavaScript - Prototypes, Prototype Chains · Issue #13 · cttin/cttin.github.io · GitHub
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。