这种方法并没有使用严格意义上的构造函数,接住原型可以基于已有的对象创建新对象,同时还不比因此创建自定义对象,
function object(o){
function F(){};
F.prototype=o;
return new F();
}
克罗克福德主张的这种原形式继承,在object内部,先创建了一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回了这个临时类型的一个新实例,
从本质上讲,object()对传入其中的对象进行了一次浅复制。看下例
var person={
name:"summer",
friends:["sum1","sum2","sum3"]
};
var anotherPerson=object(person);
anotherPerson.name="Greg";
anotherPerson.friends.push("sum4");
var yetAnotherPerson=object(person);
yetAnotherPerson.name="linda";
yetAnotherPerson.friends.push("linda2");
console.log(person.friends); // ["sum1", "sum2", "sum3", "sum4", "linda2"]
克罗克福德主张的这种原形式继承,要求必须有一个对象作为另一个对象的基础
如果有这么一个对象的话,可以把它传递给object函数,然后再根据具体需求对得到的对象加以修改即可。
在这个例子中,可以作为另一个对象基础的是person对象,于是我们把它传入到object()函数中,然后该
函数就会返回一个新的对象,这个新对象将person作为原型,所以他的原型中就包含一个基本类型值属性和一个引用类型值属性
这就意味着person.friends不仅属于person所有,而且也被anotherPerson和yetAnotherPerson所共有
实际上,这就相当于又创建了person对象的两个副本
ECMAScript5通过新增Object.create()方法规范化了原形式继承,这个方法接收两个参数:一个用作新对象原型的对象
和(可选的)一个为新对象定义额外属性的对象,在传入一个参数的情况下,Object.create()和object()方法的行为相同
var person={
name:"Nicholas",
friends:["sum1","sum2","sum3"]
}
var anotherPerson=Object.create(person);
anotherPerson.name="Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson=Object.create(person);
yetAnotherPerson.name="Linda";
yetAnotherPerson.friends.push("Linda2");
console.log(person.friends); // ["sum1", "sum2", "sum3", "Rob", "Linda2"]
Object.create()的第二个参数与Object.defineProperties()方法的第二个参数相同:每个属性都是通过自己的描述符定义的。
以这种方式指定的任何属性都会覆盖原型对象上的同名属性
// 例如:
var person={
name:"summer",
friends:["sum1","sum2","sum3"]
}
var anotherPerson=Object.create(person,{
name:{
value:"lulu"
}
});
console.log(anotherPerson.name); // lulu
// 支持Object.create()方法的浏览器有IE9+,FF4+,Safari5+,Opera12+,Chrome
在没有必要兴师动众的创建构造函数,而只想让一个对象与另一个对象保持类似的情况下,原形式继承是完全可以胜任的。
不过别忘了,包含引用类型值的属性始终都会共享相应的值,就像使用原型模式一样。