如果函数是构造函数,最好以大写字母开头。名为 foo 的函数不会将自己标识为构造函数,因此最好将其命名为 Foo。
当您设置 Child 的原型时,您不知道实例,因此无法调用Parent.apply(this,arguements);
. 如果您知道 Child是Parent,那么您可以将 Parent.appy 添加到 Child 的正文中(请参阅最后的链接)。
看起来您想用另一个动态扩展一个构造函数,最完整的方法(instanceof 和构造函数都按预期工作,父实例成员是子实例成员)是extend
为您创建实例或添加一个 init 函数初始化“父”实例成员。
如果您正在寻找诸如实现或多重继承之类的东西,用于对象可以做某事而不是某事的情况,请查看最后的链接以了解混合模式。
var extend = function(source,target,arg){
//source=Parent, target=Child
//set prototype without createing a source
//instance and without using Object.create
var fn=function(){},ret;
fn.prototype = source.prototype;
target.prototype = new fn();
//repair constructor
target.prototype.constructor = target;
//create instance
ret = new target(arg);
//add function to set source intance members
ret.extend_init=function(arg){
source.apply(this,arguments);
};
//set source intance members
ret.extend_init(arg);
//remove init
delete ret.extend_init;
return ret;
};
var Parent = function(arg){
this.name=(arg && arg.name)? arg.name:undefined;
this.age=(arg && arg.age)?arg.age:undefined;
};
Parent.prototype.whoAreYou = function(){
return "I am "+this.name+" and I'm "+this.age+
" years old.";
};
var Child = function(){
};
var t = extend(Parent,Child,{
name: "t",
age: 22});
console.log(t instanceof Child);//<=true
console.log(t instanceof Parent);//<=true
console.log(t.whoAreYou());//<=I am t and I'm 22 years old.
这会导致一些开销,因此如果您在循环中创建大量这些实例,最好在循环之前设置原型,在循环中创建和初始化实例并在之后清理:
var extend = function(source,target){
var fn=function(){},orgProto=target.prototype,
thing;
fn.prototype = source.prototype;
//overwriting Child.prototype, usually you define inheritance
// first and add Child.prototype members after but when setting
// inheritance dynamic (not having Parent.apply(this,arguments in
// Childs body) the Child's prototype get overwritten
target.prototype = new fn();
//adding the Child.prototype members
for(thing in orgProto){
if(orgProto.hasOwnProperty(thing)){
target.prototype[thing]=orgProto[thing];
}
}
target.prototype.constructor = target;
target.prototype.extend_init=function(){
source.apply(this,arguments);
return this;
};
return target;
};
var Parent = function(arg){
this.name=(arg && arg.name)? arg.name:undefined;
this.age=(arg && arg.age)?arg.age:undefined;
};
Parent.prototype.whoAreYou = function(){
return "I am "+this.name+" and I'm "+this.age+
" years old.";
};
var Child = function(){
};
Child.prototype.something=22;
//namesAndAges could be JSON data containing
// hundreds or even thousands of items
namesAndAges = [
{name:"1",age:1},
{name:"2",age:2},
{name:"3",age:3},
{name:"4",age:4},
{name:"5",age:5}
//, and many many more
];
var constr=extend(Parent,Child);
var persons=[];
for(var i = 0,len=namesAndAges.length;i<len;i++){
//Child may have constructor parameters so we pass the parameter
// object to both Child and Parent
persons.push(new constr(namesAndAges[i])
.extend_init(namesAndAges[i]));
};
delete constr.prototype.extend_init;
console.log(persons);
更多关于原型、继承、覆盖、调用超级、混合插件和this
这里的值:https ://stackoverflow.com/a/16063711/1641941