admin管理员组

文章数量:1389758

I am trying to create an object that defines getters/setters automatically for a new instance of an object. I want the setter to put the values in a separate object property called newValues. Why in the following code snippet does setting the value of prop1 actually set the value of newValues.prop2 instead of newValues.prop1?

Am I doing something silly here? It's totally possible as I am on only a few hours of sleep... :)

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'

I am trying to create an object that defines getters/setters automatically for a new instance of an object. I want the setter to put the values in a separate object property called newValues. Why in the following code snippet does setting the value of prop1 actually set the value of newValues.prop2 instead of newValues.prop1?

Am I doing something silly here? It's totally possible as I am on only a few hours of sleep... :)

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'
Share Improve this question asked May 4, 2012 at 17:50 Kevin O'HaraKevin O'Hara 3373 silver badges14 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 9

Because when you eventually use the function that you've created for the getter/setter, key has its final value. You need to close over the value of key for each iteration of the loop. JavaScript has functional scope, not block scope.

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));
    }
}

This is the usual thing where people stumble with JS: The closure in a loop problem.

This explains it quite nicely along with a solution: http://www.mennovanslooten.nl/blog/post/62

本文标签: nodejsWeird behavior with Javascript gettersettersStack Overflow