2013-11-27 27 views
1

我定义使用这个(prototype)方法有两个JavaScript类:Javascript继承与简洁的原型赋值语法

function Parent() { 
    this.a = 1; 
} 

Parent.prototype = { 
    hello : function() { 
     return "Hello I'm Parent!"; 
    }, 
    setA : function (a) { 
     this.a = a; 
    } 
}; 

function Child() { 
    this.b = 2; 
} 

Child.prototype = new Parent(); 
Child.prototype.constructor = Child; 

Child.prototype = { 
    hello : function() { 
     return "Hello I'm Child!"; 
    }, 
    setB : function (b) { 
     this.b = b; 
    } 
}; 

我使用这种技术,因为我觉得标准语法太冗长和稀疏:

Child.prototype.hello = function() {...}; 

Child.prototype.setB = function (b) {...}; 

这里的问题是,我覆盖Child.prototype(从Parent继承)失去.setA()方法(但正确覆盖.hello())。

合并两个原型的解决方案?怎么样?
这种方法会导致问题吗?

+0

考虑这个继承:'Child.prototype =的Object.create(新父());' –

+1

@马蒂亚斯可以使用的Object.create或一个辅助函数,用于在设置继承的原型部分时防止创建一个Parent实例,所以它应该是:'Child.prototype = Object.create(Parent.prototype);'您和OP执行它的每个实例特定成员的方式在Child实例中创建一个Child实例(Parent.apply(this,arguments))时,父'this.someting'被放置在Child原型上,并且(如果您正确地做到这一点)立即被遮蔽。或更糟;程序员假定Child有Parent的实例成员,并没有意识到他们实际上是共享的。 – HMR

回答

1

合并两个原型的解决方案?

是的。

怎么样?

只需编写一个运行在对象字面上的循环,并将每个属性合并到原型中。

function inherit(Child, Parent, methods) { 
    var p = Child.prototype = Object.create(Parent.prototype); 
    p.constructor = Child; 
    for (var m in methods) 
     p[m] = methods[m]; 
    return p; 
} 
function Child() { 
    Parent.call(this); 
    this.b = 2; 
} 
inherit(Child, Parent, { 
    hello : function() { 
     return "Hello I'm Child!"; 
    }, 
    setB : function (b) { 
     this.b = b; 
    } 
}); 
+1

为了完整起见,如果Child实例希望让'this.a'赋值为1或者以某种方式重新使用Parent初始化代码,那么在Child构造函数体中,你应该有'Parent.apply(this,arguments);'通常这个部分被遗忘,OP的示例代码不需要它,但我甚至看到,即使Crockford抱怨父代码在继承时也没有被重用,所以值得一提的是它可以被重用。 – HMR

+0

@HMR:谢谢你的提醒,我忘了当无意识地复制粘贴构造函数。当然它应该在那里! – Bergi

0

这里有一个例子,我从职业的JavaScript设计模式

function extend (subClass, superClass) { 
    var F = function() {}; 
    F.prototype = superClass.prototype; 
    subClass.prototype = new F(); 
    subClass.prototype.constructor = subClass; 

    subClass.superclass = superClass.prototype; 
    if (superClass.prototype.constructor === Object.prototype.constructor) { 
    superClass.prototype.constructor = superClass; 
    } // end if 
} // end extend() 

function Person (name) { 
    this.name = name; 
} // end Person() 
Person.prototype.getName = function() { 
    return this.name; 
}; // end getName() 

function Author (name, books) { 
    Author.superclass.constructor.call(this, name); 
    this.books = books; 
} // end Author() 

extend(Author, Person); 

Author.prototype.getBooks = function() { 
    return this.books; 
}; // end getBooks() 
Author.prototype.getName = function() { 
    var name = Author.superclass.getName.call(this); 
    return name + " , author of " + this.getBooks(); 
}; // end getName() 

var a = new Author("xxx", "xxx"); 
console.log(a.getName()); // xxx , author of xxx 

复制笔者列出来实现继承三路:基于类,基于原型和增加基础。

您可以阅读代码,也许读的书..