原型
我们创建的每一个函数都有一个prototype(原型)属性。这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。即protptype就是通过调用构造函数而创建的那个对象实例的原型对象。
//示例
function Persion () {};
Persion.prototype.name= "Tom";
Persion.prototype.age= 25;
Persion.prototype.sayName= function () {
console.log(this.name);
};
var persion1= new Persion();
var persion2= new Persion();
console.log(persion1.sayName === persion2.sayName); //true
/*
*上面的代码中,persion1和persion2都是函数Persion的实例,
*它们的原型对象都是Persion.prototype,
*所以等式成立
*/
构造函数--原型对象--实例关系图.png
原型链
-
查找对象属性的过程:
首先从对象实例本身开始。如果在实例中找到了具有给定名字的属性,则返回该属性的值;如果没有找到,则继续搜索指针指向的原型对象,在原型对象中查找具有给定名字的属性。如果在原型对象中找到这个属性,则返回该属性的值。
//示例
var Dog= function () {};
Dog.prototype.price= 2000;
var husky= new Dog();
console.log(husky.price); //2000
console.log(Dog.price); //undefined
/*
*查找对象属性不会去查询自身prototype对象,
*而是查找[[Prototype]]指针指向的对象。
*/
- 构造函数、原型、实例之间的关系:
每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针;而实例都包含一个指向原型对象的内部指针。
var Dog= function () {};
var husky= new Dog();
husky.price= 2000;
console.log(husky.price); //2000
console.log(Dog.price); //undefined
/*
*实例与构造函数没有连接。
*实例与构造函数的原型对象存在一个连接。(内部指针[[Prototype]])
*/
如果让原型对象等于另一个类型的实例,那么此时的原型对象将包含一个指向另一个原型的指针,相应的,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,上述关系依然成立,如此层层递进,就构成了实例与原型的链条。这就是原型链的基本概念。
function Base () {
this.a= 2;
}
Base.prototype.add= function (x,y) {
return x+y;
}
function Super () {
this.b= 1;
}
Super.prototype= new Base();
Super.prototype.subtract= function(x,y){
return x-y;
}
function Sub () {
this.name= "sub";
}
Sub.prototype= new Super();
Sub.prototype.sayName= function () {
console.log(this.name);
}
var s= new Sub();
for(var k in s){
console.log(k);
}
//name
//b
//sayName
//a
//subtract
//add
原型层次图.png
这张图片标明了实例s所有可枚举的方法所属于的原型对象。
原型指向图.png
验证一下掌握的情况:
var Animal= function () {};
var Dog= function () {};
Animal.price= 2000;
Dog.prototype= Animal;
var husky= new Dog();
console.log(husky.price); //2000
console.log(Dog.price); //undefined
参考资料
《JavaScript高级程序设计(第3版)》
《原型原型链》---汤姆大叔
《原型原型链终极详解》
网友评论