对象之间的继承有以下几个方法:
用call和apply(不推荐单独使用,定义在prototype中的属性和方法不能继承)
prototype模式(注意prototype需要先继承后定义)
传统prototype模式(推荐,关键点是Child.prototype = new Parent.prototype以及重新改变Child.prototype.constructor)
利用空对象间接继承(只继承prototype中的属性,关键点在于利用一个空的构造函数当中介)
拷贝继承(不推荐单独使用,for循环逐一拷贝)
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
function Chinese() { this.nationality = "Chinese"; } function Person(name, age) { this.name = name; this.age = age; } Person.prototype = new Chinese(); //这里因为在prototype中使用了new,则会指向Chinese console.log(Person.prototype.constructor); //Chinese(){} Person.prototype.constructor = Person; //这里需要把constructor构造函数重新改为Person console.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); //Chinese p1.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); //Chinese p1.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; }
不需要先继承后定义
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());
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());