谈谈JS继承(一):constructor,__proto__和prototype

好久没更博客了,来一篇我对JS继承的理解,其实理解了还是蛮简单的。

JS继承的设计思想

众所周知,JS采用的是一种基于原型链继承的面向对象思想,而不是像Java,C++一样基于类的面向对象。

首先JS创建实例,需要new一个构造函数,这个设计参考了C++。像这样

prototype

但是new运算符有个缺点是无法共享属性,new出来的每个实例的属性是独立的,这会造成极大的内存浪费。所以引入了prototype,构造函数设置prototype属性后,实例会共享这个属性。修改了prototype对象,就会同时影响到两个实例对象。即

__ proto __

通过内置属性__ proto __可以访问构造函数的prototype属性。即

所以我们访问一个实例的属性时,先会在内部查找,找不到再通过__ proto __向原型链上查找,一直到顶,找不到返回undefined

下面这几个如果出题你能做对吗?

new

那么知道了prototype和__ proto __,我们返回头来想想new运算符做了什么呢?

实际经历了4个步骤

1.创建一个新对象

2.建立通向构造器的原型链

3.将构造函数的作用域赋给新对象(this指向)

4.返回新对象

我们用prototype和__ proto __模拟

用一句话总结就是将构造函数本身代码实例到本身,挂载this和共享构造函数prototype属性。

constructor

继承中还有一个重要概念constructor

字面意思就是构造函数,用于指明构造函数是谁,它默认存在于prototype属性上,同时默认指向当前的构造函数。

但是由于一些书写习惯,如

这时我们需要手动矫正

当然如果你是这么填充prototype就没有这个问题了

那么我们为什么要修正constructor呢?换句话说,constructor仅仅是标识构造函数么?

其实很有必要。我们接着上面的代码

上面只是判断了Dog.prototype.constructor不是Dog,那会是什么呢?

Dog.prototype现在没有constructor这个属性,所以会沿着原型链向上找。

我们看到修正constructor的必要性显而易见,保证原型链的正确性。

总结

一行代码展现constructor,__ proto __和prototype的关系

参考:

Javascript继承机制的设计思想
Javascript – How Prototypal Inheritance really works

谈谈JS继承(一):constructor,__proto__和prototype》有1个想法

发表评论

电子邮件地址不会被公开。 必填项已用*标注