Home > Article > Web Front-end > Understanding common patterns and prototype chains
Content:
Several modes of creating objects and the process of creation
Understanding of prototype chain prototype, and prototype
Relationship with __proto__
([[Prototype]]
)
Several implementations of inheritance
a.Constructor creation
function Test() {// }
Process
Create function A prototype attribute will be created for Test by default. Test.prototype
contains a pointer pointing to Object.prototype
prototype will default to There is a constructor, and Test.prototype.constructor = Test
Other methods in prototype are inherited from Object
// 调用构造函数创建实例 var instance = new Test()
The instance here contains a pointer to the prototype of the constructor, (the pointer here is called in chrome __proto__
, also equal to [[Prototype]]
)
From the above we can know that the prototype properties created by default only have constructor and properties inherited from Object. The prototype mode is to add properties and methods to the prototype
Test.prototype.getName = ()=> { alert('name') }At this time, the instance instance has the getName method, because The pointer of the instance is pointing to Test.prototype
instance.__proto__ === Test.prototypeAs shown in the figure below
. c. Combination mode
function Test() {} Test.prototype = { getName() { alert('name') } }
Test.prototype.constructor === Object // 而并不等于Test了// 因为重写以后相当于利用字面量方式创建一个实例对象,这个实例的构造函数是指向Object本身的
Of course we can also manually assign the constructor
Test.prototype = { constructor: Test, getName() { alert('name') } }
Then there will be questions again
constructorWhat is the meaning of it? I think the meaning of constructor is just to identify the constructor to which the prototype belongs. When a certain attribute needs to be obtained, it will be searched from the instance first. If not, it will be searched according to the prototype pointed to by the pointer, and then upwards until the instance pointer
points to null. Stop searching when, for example: <pre class="hljs elm">// 1 读取nameinstance.name
// 2 instance.__proto__ === Test.prototypeTest.prototype.name
// 3 Test.prototype.__proto__ === Object.prototypeObject.prototype.name
// 4Object.prototype.__proto__ === null</pre>
When this attribute is found, it will be returned directly without continuing to search. Even if the attribute value is null, if we want to continue searching, we can pass
operator to achieve. From here we can naturally think that
are all a constructor, and their prototype pointers point to Object.prototype
, They are just like the Test
I defined here, but they are just native.d. Several useful methods
Get the prototype pointed to by the pointer of an instance<pre class="hljs elm">Object.getPrototypeOf(instance) === Test.prototype</pre>
Determine whether a property exists in the instance or in In the prototype, as shown in the figure:
Operator, regardless of whether the property is enumerable or not <pre class="hljs smali">&#39;name&#39; in instance // true
&#39;getName&#39; in instance // true</pre>
Returns true whether the property is in an instance or in a prototype, so when we need to determine a Are there two ways to do it: the attribute exists in the instance or in the prototype?
// 一种就是使用hasOwnProperty判断在实例中 // 另一种判断在原型中 instance.hasOwnProperty('getName') === false && 'getName' in instance === true
The operator is the same, but only enumerable ones will be listed The bug of the IE8 version is that no matter whether the attribute is enumerable or not, it will be listed
name是在实例中定义的,getName是在原型中定义的
Object.keys()
则不一样,它返回一个对象上所有可枚举的属性,仅仅是该实例中的
Object.keys(instance)// ["name"]
e.总结
以上讨论了构造函数,原型和实例的关系:
每个构造函数都有原型对象
每个原型对象都有一个constructor
指针指向构造函数
每个实例都有一个__proto__
指针指向原型
其实是一个道理,这里我们不难想到,将Child.prototype指向parent实例,就是利用原型实现的继承,而为了每个实例都拥有各自的colors和name,也就是基础属性,在Child的构造函数中call调用了Parent的构造函数,相当于每次实例化的时候都初始化一遍colors和name,而不是所有实例共享原型链中的colors和name。
继承的实质是利用构造函数的原型 = 某个构造函数的实例,以此来形成原型链。例如
// 定义父类function Parent() {}Parent.prototype.getName = ()=> { console.log('parent') }// 实例化父类let parent = new Parent()// 定义子类function Child() {} Child.prototype = parent // 实例化子类let child = new Child() child.getName() // parent// 此时 child.constructor === parent.constructor === Parent
a.最经典的继承模式
function Parent(name) {this.name = namethis.colors = ['red'] } Parent.prototype.getName = function() {console.log(this.name) }// 实例化父类let parent = new Parent()function Child(age, name) { Parent.call(this, name)this.age = age } Child.prototype = parent // 实例化子类let child = new Child(1, 'aaa') child.getName() // parent
这里会让我想到ES6中的class继承
class Parent { constructor(name) {this.name = namethis.colors = ['red'] } getName() { console.log(this.name) } }class Child extends Parent { constructor(age, name) {super(name) } } let child = new Child(1, 'aaa') child.getName() // parent
The above is the detailed content of Understanding common patterns and prototype chains. For more information, please follow other related articles on the PHP Chinese website!