如何按程序设置 Javascript getter/setter? (或者实际上是闭包范围)
我正在尝试按程序向 Javascript 中的对象添加 getter/setter,尽管我认为下面的代码应该可以正常工作,但它并没有按照我的预期运行。
这是我的代码:
var data = {a:1, b:2, c:3};
function Abc(data) {
var data = data || {};
for ( var key in data ) {
console.log(key, data[key]);
this.__defineGetter__(key, function() {
console.log('using getter');
return data[key];
})
}
return this;
}
abc = Abc(data);
console.log('this should be 1', abc.a);
console.log('this should be 2', abc.b);
console.log('this should be 3', abc.c);
这是我意想不到的输出,
a 1
b 2
c 3
using getter
this should be 1 3
using getter
this should be 2 3
using getter
this should be 3 3
输出对我来说绝对没有意义,但我在 Chrome 和 Webkit 上得到相同的输出,所以我猜我只是愚蠢,这不是 Javascript 的错误引擎:)
正如评论中提到的,我对“数据”的三次使用并不是很好!
I'm trying to procedurally add getters/setters to objects in Javascript and although I think the code below should simply work, it doesn't act as I expected.
here is my code:
var data = {a:1, b:2, c:3};
function Abc(data) {
var data = data || {};
for ( var key in data ) {
console.log(key, data[key]);
this.__defineGetter__(key, function() {
console.log('using getter');
return data[key];
})
}
return this;
}
abc = Abc(data);
console.log('this should be 1', abc.a);
console.log('this should be 2', abc.b);
console.log('this should be 3', abc.c);
and this is my unexpected output
a 1
b 2
c 3
using getter
this should be 1 3
using getter
this should be 2 3
using getter
this should be 3 3
the output makes absolutely no sense to me, but I get the same output on Chrome and Webkit, so I'm guessing I'm just stupid and this is not a bug of the Javascript engines :)
as the comments mention my triple use of "data" isn't really good!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当传递给
__defineGetter__
的闭包被执行时,循环已完成,key
仍保持在最后一个值。试试这个:其他一些事情:
key
上使用var
,因此key
是全局的。这并没有导致您的问题,但无论如何添加它是一个好主意。data
时,您声明了一个名为data
的新变量。那里不需要使用var
因为函数中已经有一个data
;我把它去掉了。new
,这也会导致奇怪的行为;函数顶部新的三行使其行为就像使用new
调用一样。By the time the closure that was passed to
__defineGetter__
is executed, the loop has finished andkey
remains at the last value. Try this:Some other things:
var
onkey
, sokey
was global. That wasn't causing your issue, but it's a good idea to add it anyway.data
when there was already adata
in the scope of the function. It's not needed to usevar
there since there's already adata
in the function; I removed it.new
, which was also causing odd behavior; the new three lines at the top of the function cause it to act as if it was called withnew
.@罗伯特·古尔德。代码示例中的主要问题不在于“定义 getter 和 setter”,而在于“理解闭包”。
此外,您的代码在使用此内容时无效 关键字,因为您的 Abc() 函数 this 对象指向全局 window 对象。您必须使用 new Abc() 才能正确使用 this 关键字,或者必须在 Abc() 内创建新的空对象并返回它。
1)
或
2)
如果您确实需要了解“定义 getters|setters”,请阅读:
@Robert Gould. main problem in your code sample is not in "defining getters and setters", but in "understanding closures".
Additionaly your code is invalid on using this keyword, because your Abc() function this object points to global window object. You must use new Abc() to properly use this keyword or must create new empty object inside Abc() and return it.
1)
or
2)
If you realy need to known about "defining getters|setterns" read about:
key 是
Abc
范围内的局部变量,您编写的匿名函数没有变量 key,因此它使用外部范围中的变量 key。当使用匿名函数时,该变量已更改为循环中的最后一个值,因此您会看到最后一个值。您可以使用闭包来修复此问题:在该代码中,
l_key
是匿名函数返回的另一个匿名函数的key
的本地副本。key is a local variable in the scope of
Abc
, the anonymous function you wrote has no variable key, so it uses the one from the outer scope. That variable has changed to the last value in the loop by the time the anonymous function is used, so you see the last value. You can fix this with a closure:In that code
l_key
is a local copy ofkey
to the anonymous function returned be another anonymous function.