繁体   English   中英

JavaScript中的多个原型继承

[英]Multiple prototypical inheritance in Javascript

我有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()正在进行克隆 那是正确的方法吗? 还是有更好的选择?

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

注:我有一个简单回顾一下这个这个

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执行吸气剂

Object.assign无法复制吸气剂。 而是执行它们以检索副本的值。 在父原型上执行代码可能会对父原型的状态产生影响(通过该吸气剂的设计)。 在此副本的上下文中,这可能是不良行为。

其次,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” 以下是一些相关的问答:

暂无
暂无

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

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