【问题标题】:Multiple prototypical inheritance in JavascriptJavascript 中的多原型继承
【发布时间】:2017-09-02 11:35:48
【问题描述】:

我有 2 个基类,比如 ParentClass1ParentClass2。现在我想对ChildClass做多重原型继承。

使用单父类,我的代码如下。

var ParentClass = function() {

};

ParentClass.prototype.greetUser = function(name) {
    console.log('Hi. Hello,', name);
};

var ChildClass = function(name) {
  this.greetUser(name);
};

ChildClass.prototype = Object.create(ParentClass.prototype);

var obj = new ChildClass('John');
// Hi. Hello, John

现在,当我必须从 2 个父类 继承时,我尝试了以下代码。

var ParentClass1 = function() {

};

ParentClass1.prototype.greetUser = function(name) {
    console.log('Hi. Hello,', name);
};

var ParentClass2 = function() {

};

ParentClass2.prototype.askUser = function(name) {
    console.log('Hey, how are you,', name);
};

var ChildClass = function(name) {
  this.askUser(name);
  this.greetUser(name);
};

ChildClass.prototype = Object.create(ParentClass1.prototype);
ChildClass.prototype = Object.create(ParentClass2.prototype);

var obj = new ChildClass('John');
// Error.

但这似乎只接受最后提到的 Object.create()

所以后来,它尝试将第二个Object.create() 切换到Object.assign(),然后它工作正常。

ChildClass.prototype = Object.create(ParentClass1.prototype);
ChildClass.prototype = Object.assign(ChildClass.prototype, ParentClass2.prototype);

但我担心Object.assign() 正在做克隆。那么这是正确的方法吗?或者有没有更好的选择?

很抱歉提出这个问题,冗长。提前致谢。

注意:我简要了解了thisthis

【问题讨论】:

  • Object.assign 不进行深度克隆。它很浅。

标签: javascript inheritance prototypal-inheritance


【解决方案1】:

prototype 属性进行两次赋值并不是很有用,因为最后一个会覆盖第一个。你可以这样做,因为Object.assign 接受更多参数:

Object.assign(ChildClass.prototype, ParentClass1.prototype, ParentClass2.prototype);

注意Object.assign 执行 复制。必须制作一个副本是肯定的:您需要一个与其他两个原型都不同的原型对象:两者的联合。因此,您不可避免地需要以某种方式将父原型的成员复制到目标原型对象中。

一些注意事项:

1。 Object.assign 进行浅拷贝

由于Object.assign 执行浅拷贝,您可能会遇到干扰父原型的情况。这可能是您想要或不想要的。

例子:

var ParentClass1 = function() {

};

ParentClass1.prototype.userList = [];
ParentClass1.prototype.addUser = function(name) {
    this.userList.push(name);
};

var ParentClass2 = function() {

};

ParentClass2.prototype.askUser = function(name) {
    console.log('Hey, how are you,', name);
};

var ChildClass = function(name) {
  this.askUser(name);
};

Object.assign(ChildClass.prototype, ParentClass1.prototype, ParentClass2.prototype);

var p = new ParentClass1('Parent');
var obj = new ChildClass('John');
obj.addUser('Tim'); // Added to child, but
console.log(p.userList); // now parent also has Tim...

2。 Object.assign 只复制可枚举的属性

这意味着在某些情况下您将无法获得您希望的属性。假设您还想从Array.prototype 继承,那么您会希望您的子对象具有length 属性,但由于它不可枚举,您将无法使用Object.assign 获得它:

var ParentClass2 = function() {

};

ParentClass2.prototype.askUser = function(name) {
    console.log('Hey, how are you,', name);
};

var ChildClass = function(name) {
  this.askUser(name);
};

Object.assign(ChildClass.prototype, Array.prototype, ParentClass2.prototype);

var obj = new ChildClass('John');
console.log(obj.length); // undefined
console.log(Array.prototype.length); // 0

3。 Object.assign 执行 getter

Object.assign 不能复制 getter。相反,它执行它们以检索副本的值。在父原型上执行代码可能会对父原型的状态产生影响(通过该 getter 的设计)。在此副本的上下文中,这可能是不受欢迎的行为。

其次,getter的值可以是对象的一些计算和状态的结果,每次被引用时返回不同的值。但是object.assign 只会引用它一次,然后创建一个始终具有该单一值的属性。看这个例子的效果:

var ParentClass1 = function() {

};

// Define a getter on the prototype which returns a
// random number between 0 and 999, every time it is referenced:
Object.defineProperty(ParentClass1.prototype, 'randomNumber', { 
    get: function() {
        return Math.round(Math.random() * 1000); 
    }, 
    enumerable: true 
});

var ParentClass2 = function() {};

ParentClass2.prototype.askUser = function(name) {
    console.log('Hey, how are you,', name);
};

var ChildClass = function(name) {
  this.askUser(name);
};

Object.assign(ChildClass.prototype, ParentClass1.prototype, ParentClass2.prototype);

var p = new ParentClass1('Parent');
var obj = new ChildClass('John');
console.log('different:');
console.log(p.randomNumber);
console.log(p.randomNumber);
console.log(p.randomNumber);
console.log('always same:');
console.log(obj.randomNumber);
console.log(obj.randomNumber);
console.log(obj.randomNumber);
.as-console-wrapper { max-height: 100% !important; top: 0; }

进一步阅读

将多个原型组合成一个新原型的概念通常是"mixin"。以下是一些相关的问答:

【讨论】:

  • 我在问,这是对原型继承进行多重继承的正确方法吗?或者有没有更好的办法?
  • 有不同的方法,这是其中之一。如果这符合您的需求,那就没问题了。
猜你喜欢
  • 2015-10-14
  • 1970-01-01
  • 2021-11-14
  • 2010-09-28
  • 1970-01-01
  • 2010-09-28
  • 2018-02-21
相关资源
最近更新 更多