使用Javascript getter / setter的奇怪行为

时间:2012-05-04 17:50:30

标签: javascript node.js object getter-setter

我正在尝试创建一个对象,该对象自动为对象的新实例定义getter / setter。我希望setter将值放在一个名为newValues的单独对象属性中。为什么在下面的代码片段中设置prop1的值实际设置了newValues.prop2的值而不是newValues.prop1?

我在做傻事吗?这完全有可能因为我只睡了几个小时...... :)

var Record = function(data) {
  this.fieldValues = {}
  this._data = data;
  var record = this;
  for(var key in data) {
    record.__defineGetter__(key, function() {
      return record._data[key];
    });
    record.__defineSetter__(key, function(val) {
      record.fieldValues[key] = val;
    });
  }
}

var myRecord = new Record({prop1: 'prop1test', prop2: 'prop2test'});

myRecord.prop1 = 'newvalue';

console.log(myRecord.fieldValues.prop1); // undefined
console.log(myRecord.fieldValues.prop2); // 'newvalue'

2 个答案:

答案 0 :(得分:9)

因为当你最终使用你为getter / setter创建的函数时,key有它的最终值。对于循环的每次迭代,您需要关闭key的值。 JavaScript具有功能范围,而不是块范围。

var Record = function(data) {
    var key;
    this.fieldValues = {}
    this._data = data;
    for(key in data) {
        //closure maintains state of "key" variable
        //without being overwritten each iteration
        (function (record, key) {
            record.__defineGetter__(key, function() {
                return record._data[key];
            });
            record.__defineSetter__(key, function(val) {
                record.fieldValues[key] = val;
            });
        }(this, key));
    }
}

答案 1 :(得分:3)

这是人们偶然发现JS的常见问题:循环问题中的闭包。

这很好地解释了它的解决方案:http://www.mennovanslooten.nl/blog/post/62