1.背景介绍
ECMAScript中 原型链的基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。基本的实现是利用构造函数,原型和实例的关系。即是每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针[[prototype]].由于构造函数,原型和实例存在这样的关系,如果我们让一个原型对象等于另一个构造函数的实例,那么此时这个原型对象将包含一个指向另一个原型对象的指针,这样的话,另一个原型原型中也包含着指向另一个构造函数的指针。如果另一个原型又是另一个类型的实例,那么上面的关系还是会成立。这样层层递进,就够成了实例与原型的链条,这就是所谓的原型链的基本概念。
2.知识剖析
构造函数
构造函数可以用来创建特定类型的对象,像Object Array这样的原生构造函数,在运行的时候会自动出现在执行环境中。另外,我们也可以创建自己的构造函数, 从而定义自定义的对象类型的属性和方法。
function Fish(name, color, food) {
this.name = name;
this.color = color;
this.food = food;
this.eat = function () {
alert(this.food);
};
}
var littleFish = new Fish('小鱼','五颜六色','小鱼吃虾米');
var bigFish = new Fish('大鱼','白色','大鱼吃小鱼');
littleFish.eat();
原型模式
我们创建的每一个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。prototype就是 通过调用构造函数而创建的那个对象实例的原型对象。使用原型对象的好处是让所有对象实例共享他的属性和方法。
function Fish() {
}
Fish.prototype.name = "大白鲨";
Fish.prototype.color = '白色';
Fish.prototype.food = '大白鲨吃其它鱼';
Fish.prototype.eat = function () {
alert(this.food);
};
var shark1 = new Fish();
var shark2 = new Fish();
// shark1.eat();
console.log(shark1.name);
console.log(shark2.name);
理解原型对象
不论什么时候,只要创建了一个新的函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。 在默认情况下,所有原型对象队徽自动获得一个constructor属性,这个属性指向prototype属性所在函数的指针。【看demo】
function Fish() {
}
Fish.prototype.name = "大白鲨";
Fish.prototype.color = '白色';
Fish.prototype.food = '大白鲨吃其它鱼';
Fish.prototype.eat = function () {
alert(this.food);
};
var shark1 = new Fish();
var shark2 = new Fish();
console.log(Fish);
console.log(Fish.prototype);
console.log(Fish.prototype.constructor);
创建自定义的构造函数后,其原型对象默认取得constructor属性,而其他方法则会继承自Object。当我们调用构造函数创建一个新的实例后,这个实例的内部将会包含一个指针,这个是内部属性。指向构造函数的原型对象。这个指针是[[prototype]]。这个属性还没有标准的方式访问。但是还是可以返回:Object.getPrototypeOf()方法可以返回[[prototype]
原型链
前面讲过原型链的基本实现就是将一个构造函数的实例赋值给另一个构造函数的原型。这样,这个函数的实例就会继承那构造函数的属性和方法。1.原型和原型链是JS实现继承的一种模型
//构造一个Father函数,添加属性color
function Father() {
this.color = "皮肤是黄色";
this.name = '成龙'
}
Father.prototype.getColor = function () {//给 Father函数 添加原型方法
return this.color;
};
function Child() { //构造一个Child函数,添加属性eye
this.eye = '眼睛是黑色'
}
Child.prototype = new Father(); //将Father的实例 赋值给 Child的原型
Child.prototype.getEye = function () { //给 Child添加原型方法
return this.eye;
};
var newChild = new Child(); //实例化一个 Child
console.log(newChild.constructor);
console.log(Child.prototype.constructor);
console.log(newChild.getColor());
console.log(newChild.getEye());
console.log(newChild.name);
6.扩展思考
如何访问原型对象
//------------------------------------------------原型链组合继承
//构造一个Father函数,添加属性color
function Father() {
this.color = "皮肤是黄色";
this.food = ['米饭','面包']
}
Father.prototype.eat = function () {//给 Father函数 添加原型方法
alert( this.color);
};
function Child(name,age) { //构造一个Child函数,添加属性age
Father.call(this,name);
this.age = age;
}
Child.prototype = new Father(); //将Father的实例 赋值给 Child的原型
Child.prototype.constructor = Child;
Child.prototype.getAge = function () { //给 Child添加原型方法
alert(this.age);
};
var newChild = new Child('小明同学',22); //实例化一个 Child
newChild.food.push('猪肉');
console.log(newChild.food);
newChild.eat();
newChild.getAge();
var anotherChild = new Child('比卡丘',22); //实例化一个 Child
console.log(anotherChild.food);
anotherChild.eat();
anotherChild.getAge();
console.log(newChild.constructor);
console.log(Child.prototype.constructor);
console.log(newChild.getColor());
console.log(newChild.getEye());
// console.log(Object.getOwnPropertyNames(Child.prototype));
// console.log(Object.getPrototypeOf(newChild));
7.参考文献:
1、深入理解javascript原型和闭包(4)——隐式原 http://www.cnblogs.com/wangfupeng1988/p/3979290.html
2、高级程序设计
问题:1、什么是原型链: ECMAScript中 原型链的基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。基本的实现是利用构造函数,原型和实例的关系。即是每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针[[prototype]].由于构造函数,原型和实例存在这样的关系,如果我们让一个原型对象等于另一个构造函数的实例,那么此时这个原型对象将包含一个指向另一个原型对象的指针,这样的话,另一个原型原型中也包含着指向另一个构造函数的指针。如果另一个原型又是另一个类型的实例,那么上面的关系还是会成立。这样层层递进,就够成了实例与原型的链条,这就是所谓的原型链的基本概念。
2、什么是原型继承:原型链的基本实现就是将一个构造函数的实例赋值给另一个构造函数的原型。这样,这个函数的实例就会继承那构造函数的属性和方法。
3、如何访问原型链属性:.prototype.constructor Object.getOwnPropertyNames( ) Object.getPrototypeOf()