cib*_*en1 3 javascript inheritance traits mixins object-composition
只是(模拟)多重继承是混合的唯一优点:
Object.assign( MyClassA.prototype, MyMixinB )
Run Code Online (Sandbox Code Playgroud)
与继承
class MyClass extends MyClassB {
// MyClassB = class version of MyMixinB
Run Code Online (Sandbox Code Playgroud)
在 ES6 JavaScript 中?
谢谢
不会有那么一个简短的答案。JavaScript (JS) 为构建类型/对象系统提供了许多不同的技术方法(以及如何组合它们),从而带来了实用性。
首先,正如OP(原始海报)已经意识到的那样,JS 中不存在真正的多重继承。无论选择类还是传统的基于纯函数的风格,这种语言都只提供基于原型的单一继承(可以链接)。
但是,其次,与其他编程语言 (PL) 一样,还有另一种不基于继承的代码重用和对象组合方式……它是 mixin 和/或基于特征的组合。
但我将坚持使用 OP 提供的示例代码。
Object.assign(MyClassA.prototype, MyMixinB)
Run Code Online (Sandbox Code Playgroud)
如果有人考虑MyMixinB
提供额外的行为作为基于对象的混合,例如......
Object.assign(MyClassA.prototype, MyMixinB)
Run Code Online (Sandbox Code Playgroud)
var arr = ['object', 'based', 'mixin', 'approach'];
var list = { length: 4, 0: 'the', 1: 'quick', 2: 'brown', 3: 'fox' };
console.log('(typeof arr.last) : ', (typeof arr.last));
console.log('(typeof list.last) : ', (typeof list.last));
const withObjectBasedListLastBehavior = {
last: function () {
return this[this.length - 1];
}
}
Object.assign(Array.prototype, withObjectBasedListLastBehavior);
Object.assign(list, withObjectBasedListLastBehavior);
console.log('(typeof arr.last) : ', (typeof arr.last));
console.log('arr.last() : ', arr.last());
console.log('(typeof list.last) : ', (typeof list.last));
console.log('list.last() : ', list.last());
console.log('(arr.last === list.last) : ', (arr.last === list.last));
console.log('(arr.last === Array.prototype.last) : ', (arr.last === Array.prototype.last));
Run Code Online (Sandbox Code Playgroud)
上述方法是组合和继承的结合。mixin为类似列表的结构withObjectBasedListLastBehavior
提供了一种通用的实现last
方法。该结构本身不会产生任何影响。通过Object.assign
列表last
行为可以分配给任何类似列表的结构。但是第一个示例的OP确实将mixin分配给了prototype
. 因此,除非不具有自己的last
方法的实例要调用它,否则不会使用这种新获得的行为。然后原型委托发生……现在的原型last
将在调用对象的上下文中被调用。
通过 mixin(携带此类行为的结构)提供附加行为/功能的优点是可以灵活地重复使用该结构。理想的 mixin 是原子的,并且只具有一种特定行为(一种方法)。这种行为可以在类构造函数/构造函数的体内混合,或者像上面的示例一样,它被分配给任何对象(原型对象或任何其他类型)。因此,JavaScript 中的代码重用可以通过 mixins/traits 在 2 个级别上进行:在类级别(在构造/实例化时)和在对象级别的任何时间。
这种灵活性应该不足为奇,因为 mixin/traits 只从行为角度(一个对象具有行为)对组合做出贡献,而真正的继承(也在 JS 中)负责 is a thing关系。
人们应该意识到,基于 mixin/trait 的组合和继承之间的差异并不是 JavaScript 特有的。这些概念也适用于其他 PL。从技术上讲,JS 更加灵活,因为它是基于对象的,并且具有两种委托方式:通过自动运行的原型委托隐式委托和通过调用函数的和方法直接传递上下文的显式委托。call
apply
上述提供的强烈意见的实际证明考虑了OP的第二个示例代码......
class MyClass extends MyClassB {
// MyClassB = class version of MyMixinB
Run Code Online (Sandbox Code Playgroud)
...并且确实将其更改为类似的东西...
.as-console-wrapper { max-height: 100%!important; top: 0; }
Run Code Online (Sandbox Code Playgroud)
class MyClass extends MyClassB {
// MyClassB = class version of MyMixinB
Run Code Online (Sandbox Code Playgroud)