标签:pre 些许 增加 解决 property 语法 调用 如何 自己的
原文链接:http://raganwald.com/2015/06/17/functional-mixins.html
在“原型即对象”中,我们看到可以对原型使用 Object.assign 来模拟 mixin,原型是 JavaScript 中类概念的基石。现在我们将回顾这个概念,并进一步探究如何将功能糅合进类。
首先,简单回顾一下:在 JavaScript 中,类是通过一个构造函数和它的原型来定义的,无论你是用 ES5 语法,还是使用 class 关键字。类的实例是通过 new 调用构造器的方式创建的。实例从构造器的 prototype 属性上继承共享的方法。
class Todo { constructor (name) { this.name = name || ‘Untitled‘; this.done = false; } do () { this.done = true; return this; } undo () { this.done = false; return this; } }
const Coloured = { setColourRGB ({r, g, b}) { this.colourCode = {r, g, b}; return this; }, getColourRGB () { return this.colourCode; } };
Object.assign(Todo.prototype, Coloured); new Todo(‘test‘) .setColourRGB({r: 1, g: 2, b: 3}) //=> {"name":"test","done":false,"colourCode":{"r":1,"g":2,"b":3}}
const colourCode = Symbol("colourCode"); const Coloured = { setColourRGB ({r, g, b}) { this[colourCode]= {r, g, b}; return this; }, getColourRGB () { return this[colourCode]; } };
const Coloured = (target) => Object.assign(target, { setColourRGB ({r, g, b}) { this.colourCode = {r, g, b}; return this; }, getColourRGB () { return this.colourCode; } }); Coloured(Todo.prototype);
const FunctionalMixin = (behaviour) =>
target => Object.assign(target, behaviour);
const Coloured = FunctionalMixin({ setColourRGB ({r, g, b}) { this.colourCode = {r, g, b}; return this; }, getColourRGB () { return this.colourCode; } });
Coloured(Todo.prototype) const urgent = new Todo("finish blog post"); urgent.setColourRGB({r: 256, g: 0, b: 0}); for (let property in urgent) console.log(property); // => name done colourCode setColourRGB getColourRGB
const FunctionalMixin = (behaviour) => function (target) { for (let property of Reflect.ownKeys(behaviour)) Object.defineProperty(target, property, { value: behaviour[property] }) return target; }
class Todo { constructor (name) { this.name = name || Todo.DEFAULT_NAME; this.done = false; } do () { this.done = true; return this; } undo () { this.done = false; return this; } } Todo.DEFAULT_NAME = ‘Untitled‘; // If we are sticklers for read-only constants, we could write: // Object.defineProperty(Todo, ‘DEFAULT_NAME‘, {value: ‘Untitled‘});
const shared = Symbol("shared"); function FunctionalMixin (behaviour) { const instanceKeys = Reflect.ownKeys(behaviour) .filter(key => key !== shared); const sharedBehaviour = behaviour[shared] || {}; const sharedKeys = Reflect.ownKeys(sharedBehaviour); function mixin (target) { for (let property of instanceKeys) Object.defineProperty(target, property, { value: behaviour[property] }); return target; } for (let property of sharedKeys) Object.defineProperty(mixin, property, { value: sharedBehaviour[property], enumerable: sharedBehaviour.propertyIsEnumerable(property) }); return mixin; } FunctionalMixin.shared = shared;
const Coloured = FunctionalMixin({ setColourRGB ({r, g, b}) { this.colourCode = {r, g, b}; return this; }, getColourRGB () { return this.colourCode; }, [FunctionalMixin.shared]: { RED: { r: 255, g: 0, b: 0 }, GREEN: { r: 0, g: 255, b: 0 }, BLUE: { r: 0, g: 0, b: 255 }, } }); Coloured(Todo.prototype) const urgent = new Todo("finish blog post"); urgent.setColourRGB(Coloured.RED); urgent.getColourRGB() //=> {"r":255,"g":0,"b":0}
urgent instanceof Todo //=> true urgent instanceof Coloured //=> false
Object.defineProperty(Coloured, Symbol.hasInstance, {value: (instance) => true}); urgent instanceof Coloured //=> true {} instanceof Coloured //=> true
const shared = Symbol("shared"); function FunctionalMixin (behaviour) { const instanceKeys = Reflect.ownKeys(behaviour) .filter(key => key !== shared); const sharedBehaviour = behaviour[shared] || {}; const sharedKeys = Reflect.ownKeys(sharedBehaviour); const typeTag = Symbol("isA"); function mixin (target) { for (let property of instanceKeys) Object.defineProperty(target, property, { value: behaviour[property] }); target[typeTag] = true; return target; } for (let property of sharedKeys) Object.defineProperty(mixin, property, { value: sharedBehaviour[property], enumerable: sharedBehaviour.propertyIsEnumerable(property) }); Object.defineProperty(mixin, Symbol.hasInstance, {value: (instance) => !!instance[typeTag]}); return mixin; } FunctionalMixin.shared = shared; urgent instanceof Coloured //=> true {} instanceof Coloured //=> false
标签:pre 些许 增加 解决 property 语法 调用 如何 自己的
原文地址:https://www.cnblogs.com/averyby/p/10026365.html