这将不会是个完整的教程,但会明确Javascript中一些基础的概念和机制。
我们经常看到三个关键单词,prototype
,constructor
,__proto__
,那么它们到底是什么鬼,之间又是什么样的关系。
首先贴出张图。
picture from:http://blog.csdn.net/hikvision_java_gyh/article/details/8937157
从以上图中可以看出。当一个函数F
声明时,Javascript内部会自动给函数添加一个原型属性,这个属性是一个prototype
对象。这个对象包含一个constructor
属性,是一个指向函数F
的引用。
现在就差__proto__
没出场了。先上一小段代码。
代码很简单,声明一个Base
函数,并且实例化一个base
对象。此时,base
对象会有一个__proto__
属性,这个属性指向函数Base
的原型属性,即prototype
对象。
那么总结这三个玩意就是:
-
[函数身上]
prototype
:是函数的原型属性,类型是一个对象。 -
[函数身上]
constructor
:是prototype
对象的一个属性,指向函数的引用。 -
[实例身上]
__proto__
: 实例的一个属性,指向函数的prototype
对象。
三个关系基本捋清楚了,那么就要开始一波等价模式,虽然有点绕,不过验证下我们的认识是否牢固。
– 开启等价模式 –
******
咦。。。之前不是说constructor
是在函数身上,不在对象身上。这就要归功于Javascript的原型链了,当发现base
实例中没有constructor
时,会找去实例__proto__
属性指向的原型上找,而之前我们说到了,属性__proto__
是指向函数的prototype
对象,这样就找到了constructor
属性,而constructor
属性指向函数本身。
******
函数Base
的prototype
属性的constructor
指向函数Base
本身。
******
– 关于寄生组合式继承 –
众所周知标准的寄生组合式继承如下
寄生组合式继承的好处就不赘述了,继承构造函数的部分就略过了,想了解的,可以google,详细的解读很多。我们将重点放在原型链的继承。
在谈这个方式的同时,可以先来看看,我们一般是如何判断继承关系。上面的代码用的是instanceof
方法,那么这个instanceof
内部又是如何判断的呢?
ECMAScript规范中对于instanceof
有清晰的定义,规范定义比较晦涩,涉及到很多概念,就不贴出来了,将其转换成Javascript代码的话,如下:
从这里可以看出,从实例L的原型一级一级往上找,如果找到和函数R原型属性严格等于的话,就返回为true,就判定L是R的实例。
那么再回头来看看前面的代码。
经过前面的讲述,应该很推断出,本质的判断是如此的。
那么问题来了,是不是只能这么写呢?如果这样呢?
会发现最后也能判断为true,本质也是一样。等价于如下:
暂时就谈到这了,各位晚安。