Related
This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 8 years ago.
// example A (works)
foo(function() {
myObj.save();
});
// example B (doesn't work)
foo(myObj.save);
// example C (works)
foo(myObj.save.bind(myObj));
Why is the this reference correct when myObj.save is called in example A, but not in example B?
I can force this to be correct by using bind, but what is happening in example A that is different from example B?
I don't understand why this would be different.
Functions only have a context, this, when invoked.
When you call x.y(), the this context inside y is x.
When you write x.y, you're referencing just the function y, you're not invoking it and there is no context. When you pass that function elsewhere, such as z = x.y, the context is not passed with it.
You're doing that in your second example. You're passing the function without context into foo, where there is no possible way for foo to know what the context should be. When it's invoked by foo, it's going to be invoked a simple save() call, and when this happens the this context will be window (or null in strict mode).
This is because this refers to the object on which a method was called. When you set the method of a function to a variable, or pass it in as an argument, it is no longer associated with the object it was a method of.
Multiple objects can share the same function, this is a way of dynamically reusing that function to manipulate the object instance it is a method of.
The bind method was added later to address use cases such as these.
I'm trying to get under the covers a little bit and get to understanding and not regurgitating code. I'm aware that bind, call and apply change the execution context by modifying what this points to. What I do not understand, is are arenas in which these methods are indispensable and/or lead to much shorter code. Consider the following:
var person = {
firstName: 'john',
lastName: 'doe',
fullName: function () {
console.log(this.firstName + " " + this.lastName);
}
}
//#1, binder is an html button
$('#binder').click(person.fullName.bind(person)); //john doe
//#2, anonymous is an html button
$('#anonymous').click(function () {
person.fullName(); //john doe
});
//seems strange I see this application a lot 'borrowing' a method
//why?
var o = { firstName: 'obj', lastName: 'ect' };
person.fullName.call(o); //obj ect to console
I would like to know some general paradigms about when it's good practice and/or a huge time saver to use call and apply (and bind outside of the not using anonymous functions a la function #1)
To focus on where each of these features are indispensable, I would say
apply is most useful when dealing with variadic functions. It lets you convert an array of values into an argument list.
function logwrapper(f){
return function(){
console.log("called");
return f.apply(this, arguments);
}
}
var bar = function(){ ... }
var foo = logwrapper(bar);
bind is most useful when you want to pass a method into some code that expects just a function. A common example is settimeout and other functions that expect callbacks:
setTimeout(function(){ obj.meth(); }, 100); //handwritten callback
setTimeout(obj.meth.bind(obj), 100); //Function.prototype.bind
setTimeout(bind(obj, "meth"), 100); //Some JS libraries have functions that
//let you write the object only once.
Just keep in mind that IE <=8 does not support the native Function.prototype.bind. You might need to use a polyfill or helper library in that case.
call is mostly useful for borrowing methods, as you already noticed. If this is going to be useful or not is going to depend a lot on your particular use case but an important use that is very common is using array methods on the arguments. For historical reasons, arguments doesn't have any of the usual array methods (slice, map, etc) so you need to borrow them:
function myvariadic(x){
var rest = [].slice.call(x, 1);
}
Another example you might see is the hasOwnProerty method:
for(k in obj){
if(Object.prototype.hasOwnProperty.call(obj, k)){
....
}
}
This lets you call the real hasOwnProperty method even if the object shadows it with a hasOwnProperty key of its own.
Frankly I don't give a twopenny toss about good or bad practices.
If your aim is to understand anything at all, you'd better forget about them.
This being said, to understand when it is appropriate to use call/apply or bind, what you have to understand is closures, and the specific closure of this.
I use a broad definition of closure here. Not the one you will usually get in JavaScript technical chats, where we usually talk about lexical closures.
For the purpose of this little post, let's say a closure will be anything that provides a value for any variable (this included) that lives outside the current scope of the function you're focusing on.
bind, call and apply are basically there to supply a value for this (and some other arguments as an option).
It is only useful for two things:
invoke functions or methods of a given class to an object of a different class (or no class at all).
more on that later
supply a value for this in case the current closure does not suit your needs.
For instance, passing a reference to a method loses the connection to the underlying object instance. Or using a class prototype function. Or being called in the context of an event handler where JS has set this to the DOM element that caught the event.
call & apply
call will simply set this to the value of its first argument for this particular execution of the function.
Since creating objects is so easy in JS, you might want to do something like:
Worker = function ()
{
this.things_done = 0;
}
Worker.prototype = {
do_something: function (count)
{
this.things_done += count;
}
}
var worker= new Worker(); // Worker object
var wanabee_worker = { things_done: 100 }; // classless object
Et voilà! You've just created something that has no class relation with Worker but still can use Worker methods, since it has all the required properties defined.
worker.do_something.call (wanabee_worker, 10);
allows wanabee_worker to borrow unrelated object Worker's methods.
The opposite can also be used:
function reset_work_count ()
{
this.things_done = 0;
}
reset_work_count.call (worker);
Here we have a plain function that does not have anything to do with Worker, except it uses the same properties. call allows to apply it to a Worker object.
apply does exactly the same as far as this is concerned. The only difference is the way other arguments are passed.
bind
bind will create an internal closure and return a new wrapper function that will use the parameter passed to bind as a value for this.
Typical example: bind an event handler to a specific object.
$('#binder').click(person.fullName.bind(person));
Beneath the JQuery goo, what the code does eventually is
binder.addEventListener ('click', person.fullName.bind(person), false);
If the handler was simply defined as person.fullName, it would be called with this set to the DOM element that caught the event.
In that particular case, the closure of this provided by the JS engine does not suit our needs, so we provide an alternative one using bind.
Instead of person.fullName.bind(person), you could have used:
function() { person.FullName(); }
except that
the lambda function is cumbersome and obfucates the code,
bind is an internal construct that does the closure a bit more efficiently.
You could also imagine that the object used to handle the event will be dynamically allocated/computed by some proxy function. In that case, using bind would be useless since what we want is access to the methods that will allow us to use a lambda object as one of a working class.
function event_handler (param)
{
var obj = compute_lambda_obj ();
Worker.prototype.do_something.call (ojb, param);
}
This question already has answers here:
var self = this?
(8 answers)
Closed 9 years ago.
I see in almost all examples of a knockout.js viewmodels the line var self = this and then all local variables are references as self.variableName. What is the advantage of this over using this.variableName?
Normally the main reason for using this approach is to make the current this available to subfunctions or closures. For example:
var myObject = {
param: 123,
method: function(){
alert( this.param );
},
method2: function(){
setTimeout(function(){
alert( this.param );
},100);
}
}
In the above calling myObject.method will give you the correct alert of 123. However calling myObject.method2 will give you undefined. This is because this inside the anonymous function used with setTimeout does not refer to myObject, depending on the JavaScript interpreter it will point to different things. However, if you have:
method2: function(){
var self = this;
setTimeout(function(){
alert( self.param );
},100);
}
This works because the current state of this — at the right point — is captured, and will always reference myObject for every function scope that it is available to.
The problem is not limited to the use of setTimeout. At any point where you have anonymous functions, subfunctions or closures this trick will come in handy. Sometimes people use self, or that or something a bit more descriptive depending on what the current reference represents.
rather than storing as a variable
There is an alternative to using self or any other variable to "remember" the state of this at any particular point, and that is to "bind" your anonymous or sub functions with a particular context. Many modern interpreters now support the Function.prototype.bind method, which can be used thusly:
var method = function(){
console.log(this);
};
var methodWithWindow = method.bind(window);
var methodWithDocument = method.bind(document);
var methodWithObject = method.bind({random:"object"});
Calling each of the bound methods in turn would give you the following console output:
Window
Document
Object {random:"object"}
If you wish to support older browsers you can use a polyfill, or if you prefer a much simpler implementation, one that doesn't worry about binding arguments as well. The basics of what the bind code does is the following:
!Function.prototype.bind && (Function.prototype.bind = function(context){
var method = this;
return function(){
method.apply(context, arguments);
}
})
So, how would the initial example look using bind?
method2: function(){
setTimeout((function(){
console.log(this); // `this` will be the same as the `this` passed to bind.
}).bind(this),100);
}
As you can see above, once bound, the returned function (closure) retains that specified context; so it can be passed around where ever you want and still keep a this reference to the object you want. This is useful in the method2 example because we bundle the method up with our current context and pass it to setTimeout which will execute the bound method later (long after we have exited the current block execution).
The same does occur for when using self or any other variable. The variable would be captured within the function's scope chain, and would still be there for access when the function is eventually called again. The benefit of using bind however is that you can override the context easily if you so wish, you would have to code your own specific methods to do so to override a self variable.
WARNING: It is worth noting here that when you bind a function, a new function is returned. This can cause confusing situations if you mix bound functions with event listeners and then attempt to remove the listeners using the original function rather than the bound version.
Also, because binding returns a new function, if you bind a bound function you are in fact wrapping a function in a function, with another function. You should be aware of this because it affects performance and will prove trickier to manage in terms of avoiding memory leaks. My preferred approach to binding is to use closures with their own deconstruction methods (i.e. rely on self, but make sure you have methods to nullify it's content), but this does take more forward thinking and is not so relevant in smaller JS projects; or one off function bindings — especially if the bound method is never caught in any reference.
without self and bind?
It is also worth mentioning that sometimes you can achieve the same result without using bind at all, and instead use apply — which should be natively available in anything you may choose to use. The major difference being that nothing is wrapped up with the function, and calling apply actually executes the function there and then with a different context — the first argument passed to apply.
var externalMethod = function(){
console.log(this); // will output myObject when called below
};
var myObject = {
method2: function(){
externalMethod.apply(this);
}
};
What is this?
Just to elaborate this answer with further detail about this — before the recent comments get deleted. this will refer to one of four things, depending on how the function you are using it within was called:
myObject.method()
The above will have a this of myObject, unless method has had a .bind(context) operation applied. In which case this will be whatever the last bound context was.
unattachedFunction()
Will have a this of the global context (usually window in browser environments), unless unattachedFunction has had a .bind(context) operation applied. In which case this will be whatever the last bound context was.
anyFunction.apply(otherObject)
or
anyFunction.call(otherObject)
Both will always have a this of otherObject, because calling in this way will override any binding.
new myObject()
Will have a this that refers to a new instance of myObject, this will override any binding.
Simple thought experiment
Taking all the above into account, what would this be inside referencedMethod?
var referencedMethod = myObject.method;
referencedMethod();
Correct! it will be the global context. This is why if you want to share methods with other objects or code — but still retain the original owner as context — you really need to either bind, or keep the function bundled with its owner object so you can call or apply.
Self is used to make sure the original this is maintained within the object.
This comes in handy when using event handlers and so on.
You can read more about this here
The first answer covers it basically, also it shows a good link. Check it out.
It is used for reference purposes. this under Javascript behaves different than in other languages. For more details look at MDN Docs on this
Guys can any one explain context to use call and apply methods in Javascript?
Why to use call and apply instead of calling a function directly ?
You use call or apply when you want to pass a different this value to the function. In essence, this means that you want to execute a function as if it were a method of a particular object. The only difference between the two is that call expects parameters separated by commas, while apply expects parameters in an array.
An example from Mozilla's apply page, where constructors are chained:
function Product(name, price) {
this.name = name;
this.price = price;
if (price < 0)
throw RangeError('Cannot create product "' + name + '" with a negative price');
return this;
}
function Food(name, price) {
Product.apply(this, arguments);
this.category = 'food';
}
Food.prototype = new Product();
function Toy(name, price) {
Product.apply(this, arguments);
this.category = 'toy';
}
Toy.prototype = new Product();
var cheese = new Food('feta', 5);
var fun = new Toy('robot', 40);
What Product.apply(this, arguments) does is the following: The Product constructor is applied as a function within each of the Food and Toy constructors, and each of these object instances are being passed as this. Thus, each of Food and Toy now have this.name and this.category properties.
Only if you use call or apply you can modify the this context inside the function.
Unlike other languages - in JavaScript this does not refer to the current object - rather to the execution context and can be set by the caller.
If you call a function using the new keyword this will correctly refer to the new object (inside the constructor function)..
But in all other cases - this will refer to the global object unless set explicitly through call
You use .call() when you want to cause a function to execute with a different this value. It sets the this value as specified, sets the arguments as specified and then calls the function. The difference between .call() and just executing the function is the value of the this pointer when the function executes. When you execute the function normally, javascript decides what the this pointer will be (usually the global context window unless the function is called as a method on an object). When you use .call(), you specify exactly what you want this to be set to.
You use .apply() when the arguments you want to pass to a function are in an array. .apply() can also cause a function to execute with a specific this value. .apply() is most often used when you have an indeterminate number of arguments that are coming from some other source. It is often used too pass the arguments from one function call to another by using the special local variable arguments which contains an array of arguments that were passed to your current function.
I find the MDN references pages for .call() and .apply() helpful.
If you have experience with jQuery, you will know that most functions take use of the this object. For example, collection.each(function() { ... });
Inside this function, "this" refers to the iterator object. This is one possible usage.
I personally have used .apply() for implementing a queue of requests - I push an array of arguments into the queue, and when the time comes for executing it, I take an element, and pass it as the arguments for a handler function using .apply(), thus making the code cleaner then if having to pass an array of arguments as a first argument. That's another example.
In general, just keep in mind that those ways to call a function exist, and you may one day find them convenient to use for implementing your program.
If you have experience with Object Oriented Programming then call and apply will make sense if you compare it with inheritance and override the properties or method/functions of parent class from child class. Which is similar with call in javascript as following:
function foo () {
this.helloworld = "hello from foo"
}
foo.prototype.print = function () {
console.log(this.helloworld)
}
foo.prototype.main = function () {
this.print()
}
function bar() {
this.helloworld = 'hello from bar'
}
// declaring print function to override the previous print
bar.prototype.print = function () {
console.log(this.helloworld)
}
var iamfoo = new foo()
iamfoo.main() // prints: hello from foo
iamfoo.main.call(new bar()) // override print and prints: hello from bar
I can't think of any normal situation where setting the thisArg to something different is the purpose of using apply.
The purpose of apply is to pass an array of value to a function that wants those values as arguments.
It has been superseded in all regular everyday usage by the spread operator.
e.g.
// Finding the largest number in an array
`Math.max.apply(null, arr)` becomes `Math.max(...arr)`
// Inserting the values of one array at the start of another
Array.prototype.unshift.apply(arr1, arr2);
// which becomes
arr1 = [...arr2, ...arr1]
thank you if you can help. Source of code http://ejohn.org/apps/learn/#84
1) in line 3 of the program below, where it says return context[name] what does this mean? Im guessing that it means name is bound to the context as a result of the apply function? Is that correct?
2)If my guess in 1 is correct, why does it use the [] brackets? Is that just the syntax. When I look at it, it makes me think array or object?
3) When it says apply(context, arguments) is arguments not the same as name or is arguments both context and name together? to put it another way, in the language of the call bind(Button, "click") is arguments only "click" or is it both button and click?
4) I tried to rewrite line 3 by substituting name for arguments like this
return context[name].apply(context, name);
but it didn`t work anymore, which raises the questions
a)if it is returning name bound to context (i.e. context[name]), why isn`t it sufficient to just have apply(context,name)?
b) if arguments includes both name and context, is the third line of the function essentially
return context[name].apply(context, [context, name]);
c) if my assumption in 4(b) is correct, why would we effectively have to have context passed twice in order to bind name to context? which is to say, I dont understand why line 3 doesnt work if you just write apply(context, name) instead of apply(context,arguments)
function bind(context, name){
return function(){
return context[name].apply(context, arguments);
};
}
var Button = {
click: function(){
this.clicked = true;
}
};
var elem = document.createElement("li");
elem.innerHTML = "Click me!";
elem.onclick = bind(Button, "click");
document.getElementById("results").appendChild(elem);
elem.onclick();
assert( Button.clicked, "The clicked property was correctly set on the object" );
Click me!
It may be helpful to understand the basics of JavaScript objects before diving into the specifics. Any JavaScript property can be accessed with the bracket notation, or the dot notation (if it is a valid identifier). It can be confusing since arrays also use this notation. Say there is an object of cars and their makes,
var cars = { Ford: 2007, Honda: 2010, BMW: 2011 };
Then we can access their keys using the dot notation or the bracket notation
cars.Ford // 2007
cars["Honda"] // 2010
Next, remember that functions are first class citizens in JavaScript. So you could use them as ordinary variables including storing them as object property values, in arrays, etc. Let's replace the years in the previous cars example with actual functions,
var cars = {
Ford: function() { alert("2007"); },
Honda: function() { alert("2010"); },
BMW: function() { alert("2011"); }
};
The keys Ford, Honda, and BMW can still be accessed as in the previous example with the dot or bracket notation, with the only difference that this time a function will be returned instead of the integer year.
cars["BMW"] now returns a function which can be directly invoked as
cars["BMW"](); // or
cars.BMW(); // or
var name = "BMW";
cars[name]();
That's not all. There are still two more ways to execute a function - through apply and call. The difference between apply and call is subtle but you should read up more about them.
Finally, arguments represents an array-like object that contains the arguments passed in to a function. This is best demonstrated by an example,
function whatever() {
console.log(arguments);
}
whatever(1, 2); // [1, 2]
whatever("foo", "bar", 23, [4, 6, 8]); // ["foo", "bar", 23, [4, 6, 8]]
whatever(); // undefined
Without giving any names to the function parameters, we were able to log all the arguments passed to the function. Since it is an array like object, access each argument individually as arguments[0], arguments[1], etc.
And now to answer your questions,
1) in line 3 of the program below, where it says return context[name] what does this mean? Im guessing that it means name is bound to the context as a result of the apply function? Is that correct?
context[name] is similar to the cars['Ford'] example above. It is supposed to give a function which is then invoked by calling apply on it. When that function is called, inside the function this will refer to the object - context.
2) If my guess in 1 is correct, why does it use the [] brackets? Is that just the syntax. When I look at it, it makes me think array or object?
Hopefully this was answered above.
3) When it says apply(context, arguments) is arguments not the same as name or is arguments both context and name together? to put it another way, in the language of the call bind(Button, "click") is arguments only "click" or is it both button and click?
arguments has nothing to do with either context or name. It is simply a list of the arguments/parameters that the function was called with. Hopefully the above description cleared this as well.
4) I tried to rewrite line 3 by substituting name for arguments like this
return context[name].apply(context, name);
but it didn`t work anymore
It didn't work because apply expects the second argument to be an Array, and you passed it a String. Try return context[name].apply(context, [name]); instead.
which raises the questions
a) if it is returning name bound to context (i.e. context[name]), why isn`t it sufficient to just have apply(context,name)?
b) if arguments includes both name and context, is the third line of the function essentially
return context[name].apply(context, [context, name]);
arguments has nothing to do with the context, or name. Hopefully this was cleared up in the above examples.
c) if my assumption in 4(b) is correct, why would we effectively have to have context passed twice in order to bind name to context? which is to say, I dont understand why line 3 doesnt work if you just write apply(context, name) instead of apply(context,arguments)
The above answers already answer this part.
1) context[name] just means the property of the "context" object with that name. In the case of:
bind(Button, "click");
that works out to Button["click"], which is the click() function inside the Button object
2) All objects in Javascript are a collection of properties, which can be accessed by their names. Given the definition:
var Button = {
click: function(){
this.clicked = true;
}
};
both Button.click and Button["click"] would refer to the same thing - the function click() inside the Button object.
3) The arguments keyword refers to an array-like object containing all of the arguments passed to a function. In the example, bind() is returning a newly-created function. The "arguments" referred to in that function are whatever arguments that function gets called with. In this case, it's neither context nor name, it's whatever the onclick mechanism passes to the event handler.
Here's a slightly different way to write the code that sets up the event handler:
var elem = document.createElement("li");
elem.innerHTML = "Click me!";
var boundFunction=bind(Button, "click");
elem.onclick=boundFunction;
document.getElementById("results").appendChild(elem);
Maybe this makes it more clear that when you call bind(), it returns a new function. If you were to call the boundFunction like this:
boundFunction("these", "are", "arguments")
The use of arguments is inside the returned function, so arguments would be ["these", "are", "arguments"] in this case. The arguments that were passed to "bind" are used to construct the function that bind returns, so they're no longer relevant when the bound function gets called.
4) Until you understand the basics of how returning a function from another function works, this'll be pretty confusing. The purpose of apply() is to set the "this" keyword for a particular function invocation. Given the definition of Button, you might expect to be able to do this to set up the event handler:
elem.onclick = Button.click;
This doesn't work correctly, because when the event handling code calls the Button.click function, "this" is set to the global context, rather than to the Button instance. The purpose of the bind() function is to make a function that sets "this" appropriately, then calls the function you originally passed to bind().
I have a half-completed blog entry on this which might be a simpler example:
http://codemines.blogspot.com/2010/01/javascript-by-example-functions-and.html