JavaScript getter 和 setter 在 dojo 上定义 class 没有按预期工作
JavaScript getter and setter on dojo defined class do not work as expected
我在dojo中定义了一个"class",一个属性 foo
定义了
JavaScript getter
和 setter
.
在下面的代码中,setter 从未被调用,getter 被调用了两次。
我想知道:
- 为什么这只发生在定义道场时 "class"?
- 如何解决?
我知道 dojo 自定义 getter 和 setter,但我想了解为什么在 "class" 中不起作用。
现场演示:
https://jsfiddle.net/yz8ft4eh/
require(["dojo/_base/declare"], function(declare) {
var Person = declare(null, {
_foo: null,
get foo() {
console.log('getter foo ' + this._foo);
return this._foo;
},
set foo(value) {
console.log('setter foo ' + value);
this._foo = value;
},
constructor: function(name) {
this.name = name;
this.foo = 1000;
}
});
var folk = new Person("phiggins");
folk.foo = 2000;
});
问题是 Dojo 不明白你在那里有一个 getter/setter 属性。重要的是要记住 lot 的 Dojo 是很久以前写的,甚至在 2009 年的 ES5 规范发布之前。虽然该项目处于活动状态,但一天中只有这么多时间,他们可能没有时间回去为各地更新的事物改进支持。 (也就是说,令我惊讶的是,在 getter/setter 属性被添加到 JavaScript 七年后,这在 2016 年仍然是一个问题。)
我无法在网上找到 v1.10.4 的未压缩源代码(您 fiddle 中的那个),但我可以找到 1.10.6,它使用了一个简单的 for-in
循环复制您的属性。我们可以看到 declare
调用了 safeMixin
,它是这样做的:
for (name in source) {
t = source[name];
if ((t !== op[name] || !(name in op)) && name != cname) {
if (opts.call(t) == "[object Function]") {
// non-trivial function method => attach its name
t.nom = name;
}
target[name] = t;
}
}
要支持使用 getter/setter 属性,必须在此处使用 Object.getOwnPropertyDescriptor
或类似属性。因此,它没有正确复制 属性,而是读取它的值。
您可以通过在 constructor
中初始化 属性 来解决这个问题:
require(["dojo/_base/declare"], function(declare) {
function getFoo() {
console.log('getter foo ' + this._foo);
return this._foo;
}
function setFoo(value) {
console.log('setter foo ' + value);
this._foo = value;
}
var Person = declare(null, {
_foo: null,
constructor: function(name) {
Object.defineProperty(this, "foo", {
get: getFoo,
set: setFoo
});
this.name = name;
this.foo = 1000;
}
});
var folk = new Person("phiggins");
folk.foo = 2000;
});
<link href="https://ajax.googleapis.com/ajax/libs/dojo/1.10.0/dijit/themes/claro/claro.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>
我在dojo中定义了一个"class",一个属性 foo
定义了
JavaScript getter
和 setter
.
在下面的代码中,setter 从未被调用,getter 被调用了两次。
我想知道:
- 为什么这只发生在定义道场时 "class"?
- 如何解决?
我知道 dojo 自定义 getter 和 setter,但我想了解为什么在 "class" 中不起作用。
现场演示: https://jsfiddle.net/yz8ft4eh/
require(["dojo/_base/declare"], function(declare) {
var Person = declare(null, {
_foo: null,
get foo() {
console.log('getter foo ' + this._foo);
return this._foo;
},
set foo(value) {
console.log('setter foo ' + value);
this._foo = value;
},
constructor: function(name) {
this.name = name;
this.foo = 1000;
}
});
var folk = new Person("phiggins");
folk.foo = 2000;
});
问题是 Dojo 不明白你在那里有一个 getter/setter 属性。重要的是要记住 lot 的 Dojo 是很久以前写的,甚至在 2009 年的 ES5 规范发布之前。虽然该项目处于活动状态,但一天中只有这么多时间,他们可能没有时间回去为各地更新的事物改进支持。 (也就是说,令我惊讶的是,在 getter/setter 属性被添加到 JavaScript 七年后,这在 2016 年仍然是一个问题。)
我无法在网上找到 v1.10.4 的未压缩源代码(您 fiddle 中的那个),但我可以找到 1.10.6,它使用了一个简单的 for-in
循环复制您的属性。我们可以看到 declare
调用了 safeMixin
,它是这样做的:
for (name in source) {
t = source[name];
if ((t !== op[name] || !(name in op)) && name != cname) {
if (opts.call(t) == "[object Function]") {
// non-trivial function method => attach its name
t.nom = name;
}
target[name] = t;
}
}
要支持使用 getter/setter 属性,必须在此处使用 Object.getOwnPropertyDescriptor
或类似属性。因此,它没有正确复制 属性,而是读取它的值。
您可以通过在 constructor
中初始化 属性 来解决这个问题:
require(["dojo/_base/declare"], function(declare) {
function getFoo() {
console.log('getter foo ' + this._foo);
return this._foo;
}
function setFoo(value) {
console.log('setter foo ' + value);
this._foo = value;
}
var Person = declare(null, {
_foo: null,
constructor: function(name) {
Object.defineProperty(this, "foo", {
get: getFoo,
set: setFoo
});
this.name = name;
this.foo = 1000;
}
});
var folk = new Person("phiggins");
folk.foo = 2000;
});
<link href="https://ajax.googleapis.com/ajax/libs/dojo/1.10.0/dijit/themes/claro/claro.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>