借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。
function object(o) {
function F(){}
F.prototype = o;
return new F();
}
在 object() 函数内部,先创建了一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回了这个这个临时类型的一个新实例。
var person = {
name: "Bert",
friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends); // Shelby,Court,Van,Rob,Barbie
alert(anotherPerson.friends); // Shelby,Court,Van,Rob,Barbie
alert(yetAnotherPerson.friends); // Shelby,Court,Van,Rob,Barbie
这种继承要求你必须有一个对象可以作为另一个对象的基础。如果有这么一个对象的话,可以把它传递给 object() 函数,然后在根据具体需求对得到德尔对象甲乙修改即可。
上例中的 person.friends 不仅属于 person 所有,而且也会被 anotherPerson 以及 yetAnotherPerson 共享。
ECMAScript 5 通过新增 Object.create() 方法规范化了原型式继承。这个方法接受两个参数:一个作用新对象原型的对象和一个为新对象定义额外属性的对象。
Object.assign() 方法就是基于 Object.create() 来实现的?所以可怜的 IE8上兼容不了... 所以在IE8上我们需要自定义一个类似的方法?
var person = {
name: "Bert",
friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = Object.create(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = Object.create(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends); // Shelby,Court,Van,Rob,Barbie
alert(anotherPerson.friends); // Shelby,Court,Van,Rob,Barbie
alert(yetAnotherPerson.friends); // Shelby,Court,Van,Rob,Barbie
Object.create() 方法的第二个参数与 Object.defineProperties() 方法的第二个参数格式相同;每个属性都是通过自己的描述符定义的。以这种方式指定的任何属性都会覆盖原型对象上的同名属性。
var person = {
name: "Bert",
friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = Object.create(person, {
name: {
value: "Greg"
}
});
alert(anotherPerson.name); // "Greg"
支持 Object.create() 方法的浏览器有 IE9+、Firefox4+、Safari5+Opera 12+和Chrome。
想让一个对象与另一对象保存类似的情况下,原型式继承是完全可以胜任的。不过,包含引用类型值的属性始终都会共享相应的值,就像使用原型式一样。
所以使用 Redux 推荐在 Reducer 中使用 Object.assign() 方法来重新创建 State,并且可以支持回退的原因就是原型继承,可以从原型链上追溯到上一个或者多个State的值,做到回退功能?
一直想说 Redux 的回退好牛逼,看不懂,这样一看也是可以实现的哟。