Javascript:在getter中混合(对象传播)

时间:2017-12-23 11:54:44

标签: javascript mixins getter-setter ecmascript-next

我尝试通过spread operator 语法在getter中创建混合到JS对象中,但是它似乎总是返回<body> <div id="wrapperA"></div> <div id="wrapperB"></div> </body> <script src='./test.js'></script>

HTML:

"use strict";

const mixin = {
    get wrapper() { return document.getElementById(this.wrappername); }
}

const wrapperA = {
  wrappername: 'wrapperA',
  ...mixin
}

const wrapperB = {
  wrappername: 'wrapperB',
  ...mixin
}

console.log(wrapperA);
console.log(wrapperB);

JS:

{wrappername: "wrapperA", wrapper: null}
{wrappername: "wrapperB", wrapper: null}

控制台输出:

...

This链接到一个应该起作用的扩展函数,从我可以告诉上面的代码创建了一个无意的闭包。但是,与/product/payment/checkTransaction语法相比,它读取的效果非常差。有人知道如何让代码与后一种解决方案一起使用吗? ES开发人员是否了解此问题并将在ES7中修复?

1 个答案:

答案 0 :(得分:5)

这不是错误。解释扩展语法时,将评估mixin的属性值,即wrapper getter在this设置为mixin的情况下调用。请注意,this 正在构建的新对象,而... has precedence超过了逗号排序。因此,在执行...时,最终对象不在视图中。其次,复制的属性不再是getter,而是具有原子值(不是函数)的普通属性。

使用Object.assign时执行的几乎相同的过程可以更好地理解行为:

Object.assign({
  wrappername: 'wrapperA'
}, mixin);

如果您希望使用新对象wrapper调用this getter,请执行以下操作:

"use strict";

class Wrapper {
    constructor(wrappername) {
        this.wrappername = wrappername;
    }
    get wrapper() {
        return document.getElementById(this.wrappername); 
    }
}

const wrapperA = new Wrapper('wrapperA');
const wrapperB = new Wrapper('wrapperB');

console.log(wrapperA.wrapper);
console.log(wrapperB.wrapper);
<div id="wrapperA"></div>
<div id="wrapperB"></div>

多重继承

如果你真的需要多重继承,那么请查看Ring.js这样的库,这使得这很容易。

在mixin实现on StackOverflow上有几个Q&amp; A。以下是源自this article

的众多想法之一

"use strict";
function MixinNameGetter(superclass) {
    return class extends superclass {  
        get wrapper() {
            return document.getElementById(this.wrappername); 
        }
    }
}

function MixinLetterGetter(superclass) {
    return class extends superclass {  
        get letter() {
            return this.wrappername.substr(-1); 
        }
    }
}

class Wrapper {
    constructor(wrappername) {
        this.wrappername = wrappername;
    }
}

class ExtendedWrapper extends MixinNameGetter(MixinLetterGetter(Wrapper)) {
}

const wrapperA = new ExtendedWrapper('wrapperA');
const wrapperB = new ExtendedWrapper('wrapperB');

console.log(wrapperA.wrapper, wrapperA.letter);
console.log(wrapperB.wrapper, wrapperB.letter);
<div id="wrapperA"></div>
<div id="wrapperB"></div>

虽然这有效地提供了多重继承,但是从表达式派生的类的层次结构实际上并不是高效代码的成分。

装修

另一种方法是放弃mixins的想法而改为使用装饰器:

"use strict";
function DecoratorNameGetter(target) {
    Object.defineProperty(target, 'wrapper', {
        get: function () { 
            return document.getElementById(this.wrappername); 
        }
    });
}

function DecoratorLetterGetter(target) {
    Object.defineProperty(target, 'letter', {
        get: function () {
            return this.wrappername.substr(-1); 
        }
    });
}

class Wrapper {
    constructor(wrappername) {
        this.wrappername = wrappername;
        DecoratorNameGetter(this);
        DecoratorLetterGetter(this);
    }
}

const wrapperA = new Wrapper('wrapperA');
const wrapperB = new Wrapper('wrapperB');

console.log(wrapperA.wrapper, wrapperA.letter);
console.log(wrapperB.wrapper, wrapperB.letter);
<div id="wrapperA"></div>
<div id="wrapperB"></div>

这导致了一个扁平结构(没有原型链),其中扩展发生在目标对象本身。