I am a little confused with how the closure works on this code:
function Spy(target, method) {
var result = {count: 0},
oldFn = target[method];
target[method] = function(input) {
result.count++;
return oldFn.apply(target, arguments);
}
return result;
}
So, when you assign this to a variable like
var logSpy = Spy(console, 'log')
logSpy is an object with a count property. If you were to call console.log, the overwritten function would increment the result.count value, but the result it's accessing is enclosed, correct? So how is the link made between the enclosed object and the global logSpy object? I'm guessing that the logSpy object is referencing the enclosed object because objects are passed to variables by reference? So does logSpy as an object technically not exist in the global execution context but is merely a reference to a closure?
-
I think that's correct -- defining a function inside of a closure gives that function access to all variables in that closure. I can only speak from experience, however, I don't know the inner workings of JS.sg.cc– sg.cc2015年12月01日 20:22:57 +00:00Commented Dec 1, 2015 at 20:22
-
"In JavaScript, the function object itself contains a non-accessible property pointing to an object containing the variables from its declaring scope." linkxersiee– xersiee2015年12月01日 20:30:48 +00:00Commented Dec 1, 2015 at 20:30
1 Answer 1
When you call Spy(console, 'log'), it does 4 things.
- Creates a
resultobject. - Set
oldFnto (a reference to)console.log(or ratherconsole['log']). - Sets
console['log']to a new function that "closes" aroundresultandoldFn. - Returns (a reference to)
result.
So, what's happening is that console.log is now a new function, but result and oldFn still exist in memory - they have not been garbage collected yet - because there is a reference to them in that new function.
When you call console.log it updates the count property of the result object (which you have a reference to as logSpy) and then calls the "backed-up" oldFn function with the right context/parameters.