原型 prototype 和 proto
- 所有的引用类型,都有一个隐式原型
__proto__
属性,并且指向它的prototype
原型对象 - 每个构造函数(包括普通函数)都有一个
prototype
原型对象 - 隐式原型
__proto__
属性值指向它的构造函数的显式原型prototype
属性 prototype
原型对象里的constructor
属性指向构造函数本身- 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么它会去它的隐式原型
__proto__
(也就是它的构造函数的显式原型prototype
)中寻找
实例对象的 __proto__
指向构造函数的 prototype
,从而实现继承
prototype
对象相当于特定类型所有实例对象都可以访问的公共容器
示例:
function Person(nick, age){
this.nick = nick;
this.age = age;
}
Person.prototype.sayName = function(){
console.log(this.nick);
}
var p1 = new Person('Byron', 20);
var p2 = new Person('Casper', 25);
p1.sayName() // Byron
p2.sayName() // Casper
p1.__proto__ === Person.prototype // true
p2.__proto__ === Person.prototype // true
p1.__proto__ === p2.__proto__ // true
Person.prototype.constructor === Person // true
原型链
当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾
示例:
var arr = [1,2,3]
arr.valueOf() // [1, 2, 3]
按照之前的理论,如果自身没有该方法,我们应该去 Array.prototype
对象里去找,但是你会发现 arr.__proto__
上也没有 valueOf
方法
下面是查询 valueof()
的流程图:
以下是关系图:
最后一个 null 意味着查找结束,设计上是为了避免死循环而设置的,Object 的隐式原型指向 null
arr.__proto__ === Array.prototype
true
Array.prototype.__proto__ === Object.prototype
true
arr.__proto__.__proto__ === Object.prototype
true
// 原型链的终点
Object.prototype.__proto__ === null; // true