0

I'm working on a JS framework and came across something odd (or I'm missing completely obvious)

I define properties on objects using Object.defineProperty. However using this within a for loop will result in some funky values. Somehow the last property added will always be the assigned value. For example if I'd assign something to attribute one it gets assigned to attribute three. Here's an example (and here's a fiddle http://jsfiddle.net/5xLdC/)

var Test = function(){};
var props = ['one', 'two', 'three'];
for(var i = 0; i < props.length; i++) {
  Object.defineProperty(Test.prototype, props[i], {
    get: function() {
      return this['_'+props[i]];
    },
    set: function(val) {
      this['_'+props[i]] = val;
    }
  });
}
var test = new Test();
test.one = 'one';
console.log(test.three) // => 'one'

If I'd wrap this up in a forEach loop it works perfectly fine. What I'm guess at is that they all hold the same get/set functions due to scope errors (on my part?).

Could anyone explain as to why this happens?

EDIT:

Also possible to solve with a IIFE:

get:(function(y) {
   return function() { return this['_'+props[y]]; }
})(i)
1

1 Answer 1

2

get and set are functions that all reference the same variable, i. By the time you call the function outside the loop, i is 3. When you use forEach, the function defining the properties gets the index or key as a parameter, which is a different entity in each call.

Sign up to request clarification or add additional context in comments.

2 Comments

Ah yes, but of course! See, I knew I missed something completely obvious ;-) Thanks a lot! (Accept in 7 minutes)
@JeffreyW. Almost everybody does this once. array.forEach ftw.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.