原型
原型是 js 中实现继承的过程中产生的一个概念
继承:指在一个对象的基础上创建新对象的过程,原型指在这过程中作为基础的对象.
创建对象
var o = {
f:function(){
return this.a+this.b;
}
}
var p = Object.create(o);
p.a=1;
p.b=2;
console.log(p.f());//3
通过 Object.create() 方法我们传入了 o 对象, 作为 p 对象的原型来创建 p 对象,然后 p 对象中就产生了一个叫_proto_的指针,这指针指向 o 对象.通过这个指针 p 对象就可以访问到 o 对象的 f 方法.
prototype 对象
function dog(name){
this.name=name;
return this.name;
}
var dogA = new dog('小三');
console.log(dogA);//dog{name:'小三'
使用 new 对象会生成一个 dog 对象的实例
缺点:无法共享属性和方法
比如:
function dog(name){
this.name=name;
this.species='犬科';
return this;
}
var dogA = new dog('小三');
var dogB = new dog('小四');
dogA.species = '猫科';
console.log(dogA);//dog {name: "小三", species: "猫科"
console.log(dogB);//dog {name: "小四", species: "犬科"
我们改变了 dogA 的 species,不会影响 dogB 中的 species.
每一个实例对象,都有自己的属性和方法的副本.这不仅无法做到数据共享,也是极大的资源浪费.
prototype 属性
这个属性包含一个对象,所有实例对象需要共享的属性和方法,都放在这个对象里面;哪些不需要共享的属性和方法, 就放在构造函数里面.
实例一旦创建,将自动引入 prototype 对象的属性和方法,也就是说,实例对象的属性和方法,分为两种,一种是本地的,另一种是引用的.
function dog(name){
this.name=name;
return this;
}
dog.prototype = {species:'犬科';
var dogA = new dog('小三');
var dogB = new dog('小四');
console.log(dogA.species);//犬科
console.log(dogB.species);//犬科
现在,species 属性是放在 prototype 对象中,是两个实例对象共享的.只要修改了 prototype,就会同时影响到两个实例对象.
dog.prototype.species = '猫科';
console.log(dogA.species);//猫科
console.log(dogB.species);//猫科
原型链
讲原型一个不可避免的概念就是原型链,原型链是通过前面两种创建原型 Object.create() 或 dog.prototype 的方式生成的一个_prtoto_指针来实现的.
function foo(){
foo.prototype.z=3;
}
var obj = new foo();
obj.x = 1;
obj.y = 2;
console.log(obj);//foo {x: 1, y: 2}
console.log(obj.z);//3
对象 obj 上是没有 z 的,但是他的原型链上有 z, 所以查找的时候如果对象本身不存在的话就会沿着原型链往上查找
obj.z=5;
console.log(obj.z);//5
console.log(foo.prototype.z);//3
如果对象上有的话则不会向原型链上查找,而且并不会改变原型链上的值
总结一下原型链作用:对象属性的访问修改和删除.
访问.优先在对象本身查找,没有则顺着原型链向上查找
修改.只能修改跟删除自身属性,不会影响到原型链上的其他对象.
总结
由于所有的实例对象共享同一个 prototype 对象,那么从外界看起来,prototype 对象就好像是实例对象的原型,而实例对象则好像 "继承" 了 prototype 对象一样.
来源: http://www.jianshu.com/p/678ec3eaf8a8