0

I have following function :

  function a() {
    var d = {
      foo : "text"
    };
    for(var b in c) {
      if(c.hasOwnProperty(b)) {
        d[b] = function() {
          return c[b].apply(this, arguments);
        };
      }
    }
    return d;
  }

  var c = {
    a : function() { alert(this.foo); },
    b : function() { return this.a(); }
  }

  a().a(); // nothing happens

  // but the following works :
  var c = {
    a : function() { alert(this.foo); }
  }

  a().a(); // output : text

I think this happens because of this in the .apply method. How can I fix this?

John
  • 6,080
  • 14
  • 58
  • 91

2 Answers2

1

It's not working because your iterator variable "b" in function "a" is shared by each of the closures.

Try this:

for(var b in c) {
  if(c.hasOwnProperty(b)) {
    d[b] = function(b) {
      return function() { return c[b].apply(this, arguments); };
    }(b);
  }
}

Here is the working version as a jsfiddle.

Pointy
  • 371,531
  • 55
  • 528
  • 584
0

a() executes in the global scope. When you call c[b].apply(this, arguments) it also executes in the global scope. The for loop iterates back-to-front, it comes across b first, it executes b in the global scope, which calls a in the global scope, which loops over c, which calls b in the global scope, ...

Result: RangeError: Maximum call stack size exceeded

Joeri Sebrechts
  • 10,770
  • 2
  • 33
  • 49
  • That's not really accurate. The outer "a" returns an object with its own "a" property. Thus, `a().a()` will result in that inner function having the object returned from the first `a()` as its `this` reference. – Pointy Aug 23 '12 at 15:08
  • Yeah, I noticed that myself after posting, but I figured adding another layer of indirection to the answer wasn't helping to clarify things. – Joeri Sebrechts Aug 23 '12 at 15:11