Javascript 中的多重原型继承
Multiple prototypical inheritance in Javascript
我有 2 个基数 class,比如 ParentClass1
和 ParentClass2
。现在我想对 ChildClass
.
进行多重原型继承
有一个单亲class,我的代码如下。
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 parent classes 继承时,我尝试了以下代码。
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()
正在做 克隆 。那么这是正确的做法吗?或者有没有更好的选择?
抱歉让这个问题冗长。提前致谢。
注意: 我简要了解了 this and this
对 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
属性,但由于它不可枚举,你不会用 [=16] 得到它=]:
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
执行 getters
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"。以下是一些相关的问答:
- How to use mixins properly in Javascript
- Javascript mixins when using the module pattern
- What's the difference between mixin() and extend() in Javascript libraries
我有 2 个基数 class,比如 ParentClass1
和 ParentClass2
。现在我想对 ChildClass
.
有一个单亲class,我的代码如下。
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 parent classes 继承时,我尝试了以下代码。
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()
正在做 克隆 。那么这是正确的做法吗?或者有没有更好的选择?
抱歉让这个问题冗长。提前致谢。
注意: 我简要了解了 this and this
对 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
属性,但由于它不可枚举,你不会用 [=16] 得到它=]:
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
执行 getters
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"。以下是一些相关的问答:
- How to use mixins properly in Javascript
- Javascript mixins when using the module pattern
- What's the difference between mixin() and extend() in Javascript libraries