转载

理解JS构造函数继承

对象之间的继承有以下几个方法:

  • 用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,则会指向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;   } 

不需要先继承后定义

传统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());
原文  http://hao.jser.com/archive/10073/
正文到此结束
Loading...