Javascript:在getter中混合(对象传播)
Javascript: Mixing in a getter (object spread)
我尝试通过传播 operator 语法将 getter 混合到 JS 对象中,但它似乎总是 return null
.
HTML:
<body>
<div id="wrapperA"></div>
<div id="wrapperB"></div>
</body>
<script src='./test.js'></script>
JS:
"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);
控制台输出:
{wrappername: "wrapperA", wrapper: null}
{wrappername: "wrapperB", wrapper: null}
This 链接到一个应该工作的扩展函数,据我所知,上面的代码创建了一个无意的关闭。但是,与 ...
语法相比,它的可读性很差。有人知道如何让代码与后一种解决方案一起使用吗? ES 开发者知道这个问题吗?它会在 ES7 中修复吗?
这不是错误。当解释传播语法时,mixin
的 属性 值分别被评估,即 wrapper
getter 被调用 this
设置为 mixin
.请注意,this
是 而不是 正在构造的新对象,因为 ...
has precedence 在逗号排序上。所以在执行 ...
的那一刻,最终对象不在视图中。其次,复制的 属性 不再是 getter,而是具有原子值(不是函数)的普通 属性。
使用 Object.assign
:
时执行的几乎相同的过程可能会更好地理解该行为
Object.assign({
wrappername: 'wrapperA'
}, mixin);
如果您希望 wrapper
getter 与新对象 this
一起调用,则执行:
"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 这样的库,这真的很容易。
有几个关于混合实现的问答on Whosebug. Here is one of the many ideas, derived from 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>
虽然这有效地提供了多重继承,但是从表达式派生的 类 的结果层次结构并不是高效代码的真正组成部分。
装饰器
另一种方法是放弃混入的想法,改用装饰器:
"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>
这导致了一个平面结构(没有原型链),其中扩展发生在目标对象本身。
我尝试通过传播 operator 语法将 getter 混合到 JS 对象中,但它似乎总是 return null
.
HTML:
<body>
<div id="wrapperA"></div>
<div id="wrapperB"></div>
</body>
<script src='./test.js'></script>
JS:
"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);
控制台输出:
{wrappername: "wrapperA", wrapper: null}
{wrappername: "wrapperB", wrapper: null}
This 链接到一个应该工作的扩展函数,据我所知,上面的代码创建了一个无意的关闭。但是,与 ...
语法相比,它的可读性很差。有人知道如何让代码与后一种解决方案一起使用吗? ES 开发者知道这个问题吗?它会在 ES7 中修复吗?
这不是错误。当解释传播语法时,mixin
的 属性 值分别被评估,即 wrapper
getter 被调用 this
设置为 mixin
.请注意,this
是 而不是 正在构造的新对象,因为 ...
has precedence 在逗号排序上。所以在执行 ...
的那一刻,最终对象不在视图中。其次,复制的 属性 不再是 getter,而是具有原子值(不是函数)的普通 属性。
使用 Object.assign
:
Object.assign({
wrappername: 'wrapperA'
}, mixin);
如果您希望 wrapper
getter 与新对象 this
一起调用,则执行:
"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 这样的库,这真的很容易。
有几个关于混合实现的问答on Whosebug. Here is one of the many ideas, derived from 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>
虽然这有效地提供了多重继承,但是从表达式派生的 类 的结果层次结构并不是高效代码的真正组成部分。
装饰器
另一种方法是放弃混入的想法,改用装饰器:
"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>
这导致了一个平面结构(没有原型链),其中扩展发生在目标对象本身。