对象之间的继承有以下几个方法:
用call和apply(不推荐单独使用,定义在prototype中的属性和方法不能继承)
-
prototype模式(注意prototype需要先继承后定义)
传统prototype模式(推荐,关键点是Child.prototype = new Parent.prototype以及重新改变Child.prototype.constructor)
利用空对象间接继承(只继承prototype中的属性,关键点在于利用一个空的构造函数当中介)
拷贝继承(不推荐单独使用,for循环逐一拷贝)
以上推荐使用传统prototype模式以及call和apply与拷贝继承相配合的模式
用call和apply
function Chinese() { this.nationality = "Chinese";}function Person(name, age) { Chinese.apply(this); //这里改变了Chinese中this的指向 this.name = name; this.age = age;}var p1 = new Person("Oli", 18);console.log(p1.nationality); //Chinese
传统prototype模式
function Chinese() { this.nationality = "Chinese";}function Person(name, age) { this.name = name; this.age = age;}Person.prototype = new Chinese(); //这里因为在prototype中使用了new,则会指向Chineseconsole.log(Person.prototype.constructor); //Chinese(){}Person.prototype.constructor = Person; //这里需要把constructor构造函数重新改为Personconsole.log(Person.prototype.constructor); //Person(){}var p1 = new Person("Oli", 18);console.log(p1.nationality); //Chinese
需要注意的是:在继承中,如果替换了prototype,那么新的prototype必须修改constructor属性,将这个属性指回到原来的构造函数。
利用空对象间接继承
function Chinese() {}Chinese.prototype.nationality = "Chinese";function Person(name, age) { this.name = name; this.age = age;}function F(){}; //空对象几乎不占用内存F.prototype = Chinese.prototype;Person.prototype = new F();Person.prototype.constructor = Person;Person.prototype.sayName = function() { //Person的prototype中的方法和属性需要在继承之后定义 console.log(this.name);};var p1 = new Person("Oli", 18);console.log(p1.nationality); //Chinesep1.sayName(); //Oli
可以将该方法定义为函数:
function extend(Child, Parent) { var F = function() {}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; Child.uber = Parent.prototype; //用于访问父对象的prototype,可用可不用}
举例:
function extend(Child, Parent) { var F = function() {}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; Child.uber = Parent.prototype;}function Chinese() {}Chinese.prototype.nationality = "Chinese";function Person(name, age) { this.name = name; this.age = age;}extend(Person, Chinese);Person.prototype.sayName = function() { console.log(this.name);};var p1 = new Person("Oli", 18);console.log(p1.nationality); //Chinesep1.sayName(); //Oli
拷贝继承
使用下面的函数逐一将prototype的属性和函数拷贝到对象中:
function extend(Child, Parent) { var p = Parent.prototype; var c = Child.prototype; for (var i in p) { c[i] = p[i]; } c.uber = p; }
不需要先继承后定义
传统prototype模式继承(例子)
function Parent() { this.name = "thisIsName";}Parent.prototype.sayName = function() { return this.name;};function Child() { this.age = "thisIsAge";}Child.prototype = new Parent();Child.prototype.constructor = Child;Child.prototype.sayAge = function() { return this.age;};var c = new Child();console.log(c.name);console.log(c.age);console.log(c.sayName());console.log(c.sayAge());
call和apply与拷贝继承相配合(例子)
function extend(C, P) { var p = P.prototype; var c = C.prototype; for(var i in p){ c[i] = p[i]; } c.uber = p;}function Parent() { this.name = "thisIsName";}Parent.prototype.sayName = function() { return this.name;};function Child() { Parent.apply(this); //继承构造函数内的属性和方法 this.age = "thisIsAge";}Child.prototype.sayAge = function() { return this.age;};extend(Child, Parent); //不需要先继承后定义var c = new Child();console.log(c.name);console.log(c.age);console.log(c.sayName());console.log(c.sayAge());