Why do I have to bind this function argument? [duplicate] - javascript

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.

Related

Function Context in Javascript and this Keyword [duplicate]

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 6 years ago.
Could somebody here please get this straight for all of us once and for all?
var parent = {child: function(){
console.log(this);
var log = function(){
console.log(this);};
log();
}
}
When I call parent.child()
I get:
Object{}
Window{}
Other people/ documentation on Mozilla say that this function has been invoked without any context. And
this
will be the object on which the function is invoked.
What I don't understand is how on earth this function within another object is considered to be without a context(so this defaulted to the global object). What's the logic here? Thanks
Function referenced at objects are like methods. When you directly call a function by indexing an object, this same object will be referenced by this in the scope the function will generate.
When calling a function without indexing an object, or without setting this context (with apply, bind, call, ...), if it's not at strict mode (or is at least in a global scope when at strict mode) this should be the global object.
When objects are instances of classes/interfaces/functions, their methods also capture this same object for this.
This is how it works for me:
(function() {
'use strict'
console.log(this) // undefined
})()
console.log(this) // Window{}

explicit "this" binding : how does the .bind method work? [duplicate]

This question already has answers here:
What is the use of the JavaScript 'bind' method?
(23 answers)
Closed 6 years ago.
So I've been trying to learn a bit about JS context and understanding the "this" keyword. This is some code I've been working with:
var addNumbers = function(num1, num2){
console.log(num1+num2);
}
var newAdd = addNumbers.bind(this,1,2);
newAdd();
The above logs the value 3, as it should. But if I call addNumbers.bind without the "this" keyword:
var newAdd = addNumbers.bind(1,2);
The newAdd() call returns NaN. Why does this NaN happen? and also, I only came across the solution of adding "this" as a first parameter by trying things out and not necessarily out of intuition. Why does passing "this" as a parameter work? and what context does the "this" in this case represent? Thanks.
EDIT: This question is different from any .bind() related questions because It is not asking for a general explanation of this function. I am asking about a specific use case and need a specific answer. Other suggested duplicates were more generalized and were more open to different types of answers.
.bind is used to assign the "this" context to another object
In your case, .bind(1,2) assigned "this" as 1 and the parameters are num1=2, num2=undefined, and 2+undefined is NaN in JS
If you have a function in an object, say obj.func(asd), thiswill be obj in the function func. If you want to change the context of thisyou can use bind or apply (that's like bind, but it calls directly the function, instead of creating a new one)
Simply put, because the Function#bind function always takes the function's this context as the first argument:
fun.bind(thisArg[, arg1[, arg2[, ...]]])
In your example, you are passing 1 as the value of this (which is not invalid, but is probably not what you're trying to do):
var newAdd = addNumbers.bind(1,2);
So if you don't need the this argument, you could just pass null:
var newAdd = addNumbers.bind(null, 1, 2);

Why is .call(this) used instead of parenthesis [duplicate]

This question already has answers here:
Reason behind this self invoking anonymous function variant
(5 answers)
Closed 8 years ago.
Is there a particular reason why i often encounter:
(function() {
console.log("Hello");
}).call(this);
instead of:
(function() {
console.log("Hello");
})();
It should have the same effect when passing this to call or not?
There seems to be some performance difference: http://jsperf.com/call-vs-parenthesis.
Presumably the code within that function uses this (where you just have console.log). In the version with call, this within the function is the same as this outside it. Without call, this inside the function is either the global object (loose mode) or undefined (strict mode).
If you're not using this within the function, there's no reason to be doing the call version, and I would lean toward not doing so because it's additional unnecessary complexity (and apparently a very very small performance cost).
The addition of .call(this) is important, it changes the context of the function enclosure, meaning that the this keyword will refer to the same this as the outer function enclosure.
In your particular code it doesn't make any difference because inside your function you do not refer to this at all.
this.a = 123;
(function() {
console.log(this.a); // always 123 regardless of scope
}).call(this);
That is significant assuming that this refers to something other than the window object. If this is already pointing to the window, then adding .call(this) makes no difference, since without it, by default the this will go to the window.

Why does this refer to window or object based on where parenthesis are placed? And return undefined

I am working on flexible javascript widget. In the course of some testing, I noticed that the context of this changes based on whether the parenthesis used to call a function are placed inside an object or in the global context of its call. Why do the parenthesis matter? And why would parenthesis inside the object refer to window and when placed in global context refer to the object. It seems like it would be the other way around.
Also undefined is returned in both instances. Is there a way to execute the function without returning anything?
I feel like I'm missing something important about this and don't want to miss out.
//this refers to window
var dataSource = {
read: read()
};
function read(){
console.log(this);
}
dataSource.read;
//this refers to dataSource object
var dataSource = {
read: read
};
function read(){
console.log(this);
}
dataSource.read();
Your code is doing two different things.
The first example is executing read() as the object definition is executed (read() is available because it's a function declaration and is hoisted, though this isn't related to the problem you're experiencing). It is called without any context so its this is window (as per the specification, where window is the browser's global object).
The second example has a reference to read(), which is then executed at the end of the block. Because it's executed as a property of dataSource, its this will become that. However, if you first assigned that reference to somewhere else and then invoked it via that reference, you'd again lose that this context.
For fine-grained control of this, take a look at bind(), call() and apply().
Also undefined is returned in both instances. Is there a way to execute the function without returning anything?
A function always has a return value (undefined if not explicitly set), but you're free to ignore it.
The scoping of this can be a tricky topic in javascript. That said, I can expand my answer on the general rules regarding the scope of this if need be.
But to answer your specific question, whenever you reference this inside an object literal, it by default, refers to the object literal itself.
Edit: as long as the function was invoked as a property of the object literal.
Where as, almost in any other situation I can call to mind, this will refer to the window object unless specified when invoking said function using apply() or call().
When this is used outside of objects it refers to the global object which in browser environment is window. Otherwise it refers to the last bareword before the last dot in the invocation.
For example:
function foo () {return this};
var bin = {bar:{foo:foo},foo:foo};
foo(); // returns window
bin.foo(); // returns bin
bin.bar.foo(); // returns bar
// ^
// |
// '------ last bareword before the last dot in the invocation
Now, as to why the location of the parenthesis matter. I think you should be able to guess by now:
When we add a parenthesis to a word (variable/name/reference) what we're doing is make a function call:
foo(); // call foo
If we don't add the parenthesis, what we're doing is refer to the object:
foo; // this contains the function foo
Note that not adding the parens is not calling the function. Therefore it should be obvious that when you do:
var bar = { foofoo : foo() }
What you're doing is passing the result of the function foo to bar.foofoo. The function is invoked without any "dots" in its invocation path. Therefore it doesn't belong to any object and therefore the rule of this == window applies.
On the other hand if you do:
var bar = { foo : foo }
What you're doing is assign the function foo to bar.foo. When you later call it as:
bar.foo()
the invocation contains a "dot" therefore the rule about the last object before the last dot applies.
See my previous answer to a related question for a detailed explanation on how this works in javascript: How does the "this" keyword in Javascript act within an object literal?

what's the difference between 'call/apply' and 'bind' [duplicate]

This question already has answers here:
Javascript call() & apply() vs bind()?
(24 answers)
Closed 9 years ago.
var obj = {
x: 81,
getX: function() {
console.log( this.x)
}
};
var getX = obj.getX.bind(obj);//use obj as 'this';
getX();//81
var getX = function(){
obj.getX.apply(obj);
}
getX();//also 81
The use of bind and call/apply look very similar, I want to know what's the difference between them.The two getX Function above is the same?
bind returns a function which will act like the original function but with this predefined. It is usually used when you want to pass a function to an event handler or other async callback.
call and apply will call a function immediately letting you specify both the value of this and any arguments the function will receive.
Your second example defines an anonymous function which calls apply. This is a common pattern; bind provides a standard implementation of that which allows you to do it with a simple function call (thus being quicker and easier to write).
.call() - calls the same function with the specified arguments
.apply() - calls the same function with the arguments specified in an array
.bind() - creates a new function with the same function body, with a preset value of this (the first argument) and returns that function.
In all cases, the first argument is used as the value of this inside the function.
The difference is how you make the call. If you've used bind to get back a function with a bound this value, you just call the function:
getx();
If you don't have a bound function, and you want to set this, you do so with call or apply:
someFunction.call(objectToUseAsThis, arg1, arg2);
// or
someFunction.apply(objectToUseAsThis, [arg1, arg2]);
Note that if you have a bound function (like your getX), using call on it is pointless, because the this you supply will just get overridden by the bound this. (Using apply might still be useful, if you have an array of values you want to ass as arguments.)

Categories

Resources