简体   繁体   English

Javascript:继承原型而不重定义构造函数

[英]Javascript: Inherit form a prototype without redefining the constructor

I've got a problem understanding javascript inheritance and constructors, despite manuals like https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript and http://robotlolita.me/2011/10/09/understanding-javascript-oop.html . 尽管有https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScripthttp://robotlolita.me/2011/10之类的手册,但我在理解javascript继承和构造函数时遇到了问题/09/understanding-javascript-oop.html

I would like to create a prototype and children inheriting from it. 我想创建一个原型,并从中继承子代。 The prototype has a constructor (or in other words, is a function). 该原型具有一个构造函数(或换句话说,是一个函数)。 I want the children to inherit this constructor, instead of re-defining the constructor for each and every child. 我希望孩子继承此构造函数,而不是为每个孩子重新定义构造函数。 The constructor of the parent is going to do quite a lot of stuff, the code for which I don't want to duplicate in the children. 父级的构造函数将做很多事情,我不想在子级中重复的代码。 And even the list of arguments for the constructor might change, in which case I would only like to change them in the parent constructor, not every child as well. 甚至构造函数的参数列表也可能会更改,在这种情况下,我只想在父构造函数中更改它们,而不是每个子控件都更改。

So an example that works on jsfiddle (also see https://jsfiddle.net/9pj1avjh/10/ ): 因此,一个适用于jsfiddle的示例(另请参见https://jsfiddle.net/9pj1avjh/10/ ):

First the preamble of running tests and a few functions to save typing (skip ahead): 首先是运行测试的序言和一些保存键入的功能(向前跳过):

function sayHello2(msg,name){
    document.write(name+": "+msg+" "+this.url+"<br />");
}

function runtest(){
    var c = new child('google.com');
    c.sayHello("Website:","dolf");

    var p = new proto("yahoo.com");
    p.sayHello("Website:");

    document.write("<br />");

}

Define the prototype/parent: 定义原型/父:

var proto = function(url){
    this.url = url
}
proto.prototype.sayHello = function(msg){
    document.write(msg+" "+this.url+"<br />")
}

This is the meat. 这是肉。 It shows the desired behaviour, but it means i always have to redefine the constructor in each child, which I don't want. 它显示了所需的行为,但这意味着我总是必须在每个孩子中重新定义构造函数,而这是我所不希望的。

var child = function(url){
    this.url = url
}
child.prototype = Object.create(proto.prototype);
child.prototype.sayHello = sayHello2
runtest()

This is more along the lines of what I want code-wise, but not the behaviour. 这更多地符合我想要的代码方式,而不是行为方式。 This case causes this.url to be undefined in child: 这种情况导致this.url在child中未定义:

var child = function(){
}
child.prototype = Object.create(proto.prototype);
child.prototype.constructor = proto.prototype.constructor
child.prototype.sayHello = sayHello2
runtest()

And this doesn't work either, because it causes sayHello2 to also be used on proto instead of just child 而且这也不起作用,因为它导致sayHello2也可以在proto上使用,而不仅仅是孩子

var child = proto.prototype.constructor
child.prototype = Object.create(proto.prototype);
child.prototype.sayHello = sayHello2
runtest()

It takes a while to understand what you meant by redefining constructor. 需要花费一些时间来理解重新定义构造函数的含义。 What you want to do is to call the parent's constructor when instantiating the child. 您要做的是在实例化子级时调用父级的构造函数。

So you don't want this, ie reassigning this.url = url , right? 因此,您不希望这样做,即重新分配this.url = url ,对吗?

var child = function(url, anotherFancyArg){
    this.url = url;
    this.anotherFancyArg = anotherFancyArg;
}

Do this instead: 改为这样做:

var child = function(url, anotherFancyArg){
    proto.apply(this, arguments);
}

Now you can access url and anotherFancyArg inside your child instance using this reference: this.url , this.anotherFancyArg , eg 现在,您可以使用以下引用访问子实例内的url和anotherFancyArg: this.urlthis.anotherFancyArg ,例如

var c = new child('google.com', 'abc');
console.log(c.url); // you get google.com here

One more thing I noticed. 我注意到了另一件事。 This is wrong: 这是错误的:

child.prototype = Object.create(proto.prototype);
child.prototype.constructor = proto.prototype.constructor;

Do this instead: 改为这样做:

child.prototype = Object.create(proto.prototype); // you inherit from parent's prototype
child.prototype.constructor = child; // but you instantiate the child object

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM