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
  • 7,500
  • 16
  • 62
  • 95
  • 3
    Oh god. Why would you write such a complicated behavior?! – Florent Aug 23 '12 at 14:54
  • @Florent just to make life easier.... – Naftali Aug 23 '12 at 14:55
  • function a() will be used like 100 or 1000 times, so I don't want it to contain a lot of big functions, so I am trying to link somehow a().a() to c.a() without creating it each time in a() function. I can't create global functions because a lot of functions may be already defined by javascript. – John Aug 23 '12 at 14:57
  • @Florent ^^ do you have a translator?! – Naftali Aug 23 '12 at 14:59
  • possible duplicate of [JavaScript "this" keyword](http://stackoverflow.com/questions/3127429/javascript-this-keyword) – Qantas 94 Heavy Mar 01 '14 at 01:19

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
  • 405,095
  • 59
  • 585
  • 614
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
  • 11,012
  • 3
  • 35
  • 50
  • 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