2

オブジェクトの新しいインスタンスに対してゲッター/セッターを自動的に定義するオブジェクトを作成しようとしています。セッターが値をnewValuesと呼ばれる別のオブジェクトプロパティに配置するようにします。次のコードスニペットで、prop1の値を設定すると、実際にはnewValues.prop1ではなくnewValues.prop2の値が設定されるのはなぜですか?

私はここで愚かなことをしていますか?私はほんの数時間の睡眠を取っているので、それは完全に可能です... :)

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'
4

2 に答える 2

9

ゲッター/セッター用に作成した関数を最終的に使用すると、key最終的な値が得られるためです。keyループの反復ごとに for の値を閉じる必要があります。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));
    }
}
于 2012-05-04T17:53:25.527 に答える
3

これは、人々が JS でつまずく通常のことです: ループの問題でのクロージャ。

これは、解決策とともにそれを非常にうまく説明しています:http://www.mennovanslooten.nl/blog/post/62

于 2012-05-04T17:55:17.373 に答える