It's frustrating to have to manually set the scope of an object every time I declare a callback in JavaScript, but it's a fact of life. I wondered if I could do it by passing [mycallback].apply as the callback, and the scope object as an argument, like so:
var f = function() { console.log(this.x); };
var o = {x: 3};
setTimeout(f.apply, 1000, o);
As far as I can tell, this should call f with o as the scope, but instead Chrome gives me "Uncaught TypeError: Function.prototype.apply was called on [object DOMWindow], which is a object and not a function". Why doesn't this work?
You can achieve this by calling bind(this) for your function: function myFunction() { console. log(this); } // bind(this) creates a new function where the value of 'this' is fixed var boundFunction = myFunction. bind(this); // It's also possible to replace the function by it's bound version myFunction = myFunction.
The Difference Between call() and apply() The difference is: The call() method takes arguments separately. The apply() method takes arguments as an array. The apply() method is very handy if you want to use an array instead of an argument list.
apply() The apply() method calls the specified function with a given this value, and arguments provided as an array (or an array-like object).
prototype. call() The call() method calls the function with a given this value and arguments provided individually.
For the same reason you need to "set the scope" in the first place. Only the apply
function is sent to setTimeout
, its association with function f
is lost. Thus Javascript assigns the global object, window
, to this
, as it would in any other case.
It is interesting to note that apply
, while being a native function, is not special or magical in some way, and behaves in a way consistent to user defined functions in the setting of the this
variable.
@MooGoo's answer is correct, but perhaps more explanation is needed.
When you call the function apply
on f
like this:
f.apply(ctx, args);
...then you're executing apply
in the context of f
.
But when you pass a reference to apply
to a function, like this:
setTimeout(f.apply, 1000, o);
...that's all you're doing: passing a reference to the function f.apply
. This is equivalent to passing Function.prototype.apply
because:
console.log(f.apply === Function.prototype.apply); // true
Any connection to f
is lost in window.setTimeout
. It receives a reference to the generic apply
function of Function.prototype
. Nothing more. No context.
Therefore, as in any other case where an explicit context is not set, the apply
function is called with window
as its context object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With