- 原型
可以从下面这几个要点来理解,下面几条必须记住并且理解。
1、所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(null除外)
2、所有的引用类型(数组、对象、函数),都有一个__proto__
属性,属性值是一个普通的对象
3、所有的引用类型(数组、对象、函数),__proto__
属性值指向它的构造函数的prototype属性值
4、所有的函数,都有一个prototype属性,属性值也是一个普通的对象
通过代码解释一下
接下来看一个简单的代码示例:
执行printName时很好理解,但是执行alertName时为什么是这个结果呢?这里再记住一个重点:当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto__
(即它的构造函数的prototype)中寻找,因此f.alertName就会找到Foo.prototype.alertName。
- 原型链
还是接着上面的示例,如果执行f.toString(),又会发生什么?为什么是这个结果呢?
因为f本身没有toString(),并且f.__proto__
(即Foo.prototype)中也没有toString。这个问题还是得拿出刚才那句话——当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto__
(即它的构造函数的prototype)中寻找。
如果在f.__proto__
中没有找到toString,那么就继续去f.__proto__.__proto__
中寻找,因为f.__proto__
就是一个普通的对象而已!
》f.__proto__
即Foo.prototype,没有找到toString,继续往上找
》f.__proto__.__proto__
即Foo.prototype.__proto__
。Foo.prototype就是一个普通的对象,因此Foo.prototype.__proto__
就是Object.prototype
,在这里可以找到toString
》因此f.toString最终对应到了Object.prototype.toString
这样一直往上找,你会发现是一个链式的结构,所以叫做“原型链”。如果一直找到最上层都没有找到,那么就宣告失败,返回undefined。最上层是什么 —— Object.prototype.__proto__ === null