var person = { name: 'aa', firends: ['zhangsan','lisi','wangwu'] }; var anthorperson = object(person); anthorperson.name = "bb"; anthorperson.firends.push("zhaoliu"); var aperson2 = object(person); aperson2.name = 'cc'; aperson2.firends.push("longen"); console.log(person.firends); // ["zhangsan", "lisi", "wangwu", "zhaoliu", "longen"];
这样的原型继承是必须有一个对象作为另一个对象的基础,如果有这么一个对象的话,可以把它传递object()函数;
ECMAScript5中新增Object.create()方法规范了原型式的继承,这个方法接收2个参数,第一个是用作新对象的原型的对象,第二个参数是可选的,含义是一个新对象定义额外属性的对象;比如如下代码:
var person = { name: 'aa', firends: ['zhangsan','lisi','wangwu'] }; var anthorperson = Object.create(person); anthorperson.name = "bb"; anthorperson.firends.push("zhaoliu"); var bperson = Object.create(person); bperson.name = 'longen'; bperson.firends.push("longen"); console.log(person.firends); // ["zhangsan", "lisi", "wangwu", "zhaoliu", "longen"]
Object.create()方法的第二个参数与Object.defineProperties()方法的第二个参数格式相同:每个属性都是通过自己的描述符定义的。以这种方式指定的任何属性都会覆盖原型对象上的同名属性。
var person = { name: 'aa', firends: ['zhangsan','lisi','wangwu'] }; var anthorperson = Object.create(person,{ name: { value: 'bb' } }); console.log(anthorperson.name); //bb
目前支持Object.create()方法的浏览器有 IE9+,Firefox4+,Safari5+,Opera12+和chrome;
理解寄生组合式继承
前面我们理解过组合式继承,组合式继承是javascript最常用的继承模式,不过,它也有缺点,它会调用两次超类型的构造函数,第一次在继承属性的时候,调用,第二次在继承方法的时候调用,如下代码:
function Animal(name) { this.values = ["aa",'bb']; this.name = name; } Animal.prototype.sayName = function(){ return this.name; } function Dog(name,age){ // Dog继承属性 Animal.call(this,name); this.age = age; }; // 继承方法 Dog.prototype = new Animal(); Dog.prototype.constructor = Dog; Dog.prototype.sayAge = function(){ return this.age; }
如上面的继承属性;Animal.call(this,name);
和继承方法Dog.prototype = new Animal();
当第一次继承属性的时候,会继承Animal中的name和values,当第二次调用继承方法的时候,这次又在新对象中创建了实例属性name和values,这次创建的属性会覆盖之前继承的属性;因此我们可以使用寄生组合式继承;
寄生组合式继承的思想是:是通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。本质上是使用寄生式继承来继承超类型中的原型,然后再将结果指定给子类型的原型,寄生组合式的基本模式如下代码:
function inheritPrototype(Dog,Animal) { var prototype = object(Animal.prototype); prototype.constructor = Dog; Dog.prototype = prototype; }
inheritPrototype该方法接收2个参数,子类型构造函数和超类型构造函数,在函数内部,先创建一个超类型的一个副本,。第二步是为创建的副本添加constructor 属性,从而弥补因重写原型而失去的默认的constructor 属性。
最后一步,将新创建的对象(即副本)赋值给子类型的原型。这样,我们就可以用调用inherit-Prototype()函数的语句,去替换前面例子中为子类型原型赋值的语句了,
如下代码演示:
function object(obj) { function F() {}; F.prototype = obj; return new F(); } function inheritPrototype(Dog,Animal) { var prototype = object(Animal.prototype); prototype.constructor = Dog; Dog.prototype = prototype; } function Animal(name) { this.values = ["aa",'bb']; this.name = name; } Animal.prototype.sayName = function(){ return this.name; } function Dog(name,age){ // Dog继承属性 Animal.call(this,name); this.age = age; }; inheritPrototype(Dog,Animal); var dog1 = new Dog("wangwang",12); dog1.values.push("cc"); console.log(dog1.sayName()); // wangwang console.log(dog1.values); // ["aa", "bb", "cc"] var dog2 = new Dog("ww2",14); console.log(dog2.sayName()); // ww2 console.log(dog2.values); // ["aa", "bb"]
如上使用寄生组合继承只调用了一次超类型;这就是他们的优点!