How is "This" assigned when calling an anonymous function using "Call"? - javascript

From MDN:
var animals = [
{species: 'Lion', name: 'King'},
{species: 'Whale', name: 'Fail'}
];
for (var i = 0; i < animals.length; i++) {
(function (i) {
this.print = function () {
console.log('#' + i + ' ' + this.species + ': ' + this.name);
}
this.print();
}).call(animals[i], i);
}
In the example above, how is "this" being used in the anonymous function inside the "animals" loop? I am curious as to why "this" is referencing the animal object instead of the window.
If I were, for example, to remove animals[i] from the arguments, then everything is undefined. Does that mean that anonymous functions derive their "identity" from the first parameter they receive or is something else going on?
Thanks in advance!

Isn't this explained in the documentation of function.call() you quote yourself?
fun.call(thisArg[, arg1[, arg2[, ...]]])
Parameters
thisArg The value of this provided for the call to fun. [...]
and later:
Description
You can assign a different this object when calling an existing function.
So you are right, animals[i] is used as this inside a function. You can treat it as implicit, hidden parameter that always has this name.

It's this part:
}).call(animals[i], i);
By calling with .call(), the value for this is specified explicitly.
There are two similar functions available from the Function prototype: .call() and .apply(). They both allow a function (any function, anonymous or not — there's no real difference) to be invoked with some particular value (a reference to an object) as this.
The value of this is always set one way or another when a function is invoked. If the reference to the function is determined by a . or [ ] expression:
something.fn( whatever );
something[ expression ](whatever);
then the value of this is the value of the base object ("something" in the above examples). Mr. Eich calls that the "receiver", which makes sense if you think of function calls like Smalltalk messages.
If you call a function without a base object, then the value of this is either the global object, or null if you're in "strict" mode.

Because you are using call which is defined as:
call(thisScope, args)
So the fact you're passing in animal[i] as thisScope means this == animal[i].

Related

Parameter correspondence: callback vs. closures (?)

With javascript closures and callbacks, I am confused on the difference between why the parameters that a named, nested function take are different (inherited from the outer function?) than a closure's parameters. For example:
var filter = function (collection, test) {
var newArray = [];
each(collection, function (value) {
if (test(value)) {
newArray.push(value);
}
});
return newArray;
};
The filter function operates on the each function. What input does the "value" parameter (in each) correspond to? Does a callback function's parameter automatically line up with filter's first parameter because they are both the first parameter of their respective functions? If the outer function and the inner one both accepted another parameter, would those line up because of their position as well? The parameter relationship between the inner/outer function here seems to be different from a closure's parameter (the closure seems to accept a new parameter; its parameters don't line up with the outer one's parameters) For example:
var outer = function(par1, par2) {
var hold = par1 + par2;
function inner(par3) {
return par3 + par1 + par2;
}
return inner;
};
var closure = outer (5,4);
closure(2);
I see that the inner function is returned from the outer function (when stored in another variable) and takes its own parameter separate from the outer function.
Do named/established functions inherit their parameter correspondence from their enclosing functions?
Do callback functions take on their own parameter - separate from their enclosing function - because they are returned out of that function and saved to a variable?
What input does the "value" parameter (in each) correspond to?
That depends on what each does. It isn't a standard JS global and you haven't shared your definition of it.
Does a callback function's parameter automatically line up with filter's first parameter because they are both the first parameter of their respective functions?
No. The arguments pass to any function are dependant on the code that calls that function.
If the outer function and the inner one both accepted another parameter, would those line up because of their position as well?
No.
Do named/established functions inherit their parameter correspondence from their enclosing functions?
No.
Do callback functions take on their own parameter - separate from their enclosing function
Yes
because they are returned out of that function and saved to a variable?
No. It is because they are functions.
function outer(foo, bar) {
console.log("Outer gets foo " + foo + " because foo is a argument of outer");
console.log("Outer gets bar " + bar + " because foo is a argument of outer");
return inner;
function inner(baz) {
console.log("Inner gets foo " + foo + " because foo is a variable still in scope");
console.log("Inner gets bar " + bar + " because bar is a variable still in scope");
console.log("Inner gets baz " + baz + " because baz is an argument of inner");
}
}
var returned_inner = outer(1, 2);
returned_inner(3);
With javascript closures and callbacks, I am confused on the difference between why the parameters that a named, nested function take are different (inherited from the outer function?) than a closure's parameters.
Your confusion problem springs from the simple fact that, most of the time, when you are using a callback, the function that actually calls it is written by someone else and you never look at it.
I think I can sum up the answer to all of the questions by saying that there is absolutely no requirement at all for the parameters of an inner function to have anything at all to do with the parameters of the enclosing function.
They are completely unrelated values.
For example:
function f(a, b, c, d, e) {
// You mentioned "named, nested" function in your question...
return function unusedName(x) {return x}
}
console.log(f(1, 2, 3, "four", 25/5)(100));
will display 100.
Of course, in reality, you would want the inner function to somehow or other use the parameters of the outer function, otherwise the parameters to the outer function are useless.
But there is no requirement that they "line up." How you create your closure, that is how your returned inner function decides to use the values from the environment provided by the outer function, is wholly up to you. The language itself enforces nothing.
Please consider changing most of the hypotheses in the question :-)
Identifier scope.
When javascript code uses an unadorned identifier (such as a variable name, the name of an object or the name of a function) inside a function, the javascript engine looks to see if the identifier is the name of a local variable, the name of a nested function defined within the same function body, or the name of a formal parameter. If not found it will search for the identifier, in the same manner, in a next most outer function (if a function searched is nested), or look for the identifier in global scope if the last function searched was itself global.
Hence there is no "lining up" of nested function parameters, there is just searching the scope chain. Outer function parameters, variables and named function definitions are all in scope of inner functions. There is no automatic "relationship" between formal parameter definitions in different functions unless planned by the programmer.
Closures
Be careful about categorizing functions as call backs or closures. Often a call back function forms a closure. In summary, a closure is caused by keeping a reference to a nested function after its outer function has returned. This can result from storing a reference to the inner function either before or after the outer function returns, or by passing a reference to the inner function to some other function for use as an asynchronous call back. A long as reference to the inner function is being held somewhere, any values it references within its scope chain cannot be made available for garbage collection because they are accessible.
forEach
The each function appears to be an iterator function being applied to the collection passed as an argument. Javascript supports a standardized forEach to iterated over Array, Map and Set objects. Please refer to documentation for further details on how it is called and calls back call back function.

When and why to use Call and Apply?

Firstly I came to know the difference between apply() and call().
function theFunction(name, profession) {
alert("My name is " + name + " and I am a " + profession + ".");
}
theFunction("John", "fireman");
theFunction.apply(undefined, ["Susan", "school teacher"]); // This call be called theFunction("Susan", "school teacher");, why use apply
theFunction.call(undefined, "Claude", "mathematician"); // This call be called theFunction("Claude", "mathematician");, why use call
From the above code, all the 3 function call displays the alert message.
What are the advantages/disadvantages of using apply and call, over normal function call, and when is it appropriate to use apply/call, please clarify me.
One more thing, what if the function is a prototype based function:
Function.prototype.theFunction = function(name, profession) {
alert("My name is " + name + " and I am a " + profession + ".");
}
Then how to call this function bu using apply or call. I tried this way:
theFunction.apply(undefined, ["Susan", "school teacher"]);
theFunction.call(undefined, "Claude", "mathematician");
but resulted in error.
"ReferenceError: theFunction is not defined"
As you have said it seems that you already know what these to functions apply() and call() actually do, but in terms of their uses, I'd say they are used mostly when you want to provide your function with a specific object of your own, as its this value in its context.
One of the most popular use of these two is to handle array-like objects like arguments objects in the function:
function(){
//let's say you want to remove the first parameter from the arguments object
//you can make sure that
console.log(arguments instanceof Array);//false
//as you see arguments is not an actual array object but it is something similar
//and you want slice out its value
var myparams = Array.prototype.slice.call(arguments, 1);
//here you have myparams without your first argument
console.log(arguments);
}
Let's go with another example. Say we have an independent function like:
function getName(){
console.log(this.name);
}
Now you can use it for any kind of JavaScript object that has a name attribute:
var myInfo = {
name: 'SAM'
};
now if you do:
getName.call(myInfo);
what it does is printing out the name attribute or you can try it on the function itself:
getName.call(getName);
which would print out the function's name ("getName") in the console.
But similar to my first example, it is usually used when you want to use functions that are not in the object's prototype chain. The other example of that could be:
//let's say you have an array
var myArray = [1 , 2];
//now if you use its toString function
console.log(myArray.toString());//output: "1,2"
//But you can use the Object toString funcion
//which is mostly useful for type checking
console.log(Object.prototype.toString.call(myArray));//output: "[object Array]"
This post gives a very detailed explanation of call() and apply().
TLDR;
Both call() and apply() are methods we can use to assign the this
pointer for the duration of a method invocation
The apply() method is identical to call(), except apply() requires an
array as the second parameter. The array represents the arguments for
the target method.
The main difference is that apply lets you invoke the function with arguments as an array; call requires the parameters be listed explicitly.
It Will Give You More Explaination
POST

Access function propertes (.caller) without specifying it's own name

In JavaScript you can access a function's "functional properties", for instance caller. (Actually, I do not even know if the "functional property" is a right word.)
For example:
func0 = function() {
console.log(typeof func0.caller)
}
func1 = func0
func1()
var o = { func2: func0, func3: function(){ console.log(typeof o.func3.caller) } }
o.func2()
o.func3()
As you can see, you must provide a function name before you can add .caller. But if the function is anonymous or for some reason I do not want to use the name (maybe I plan to rename the fucntion in the future): can I still access caller?
What you are accessing is the arguments object that is 'assigned' to every function. So you don't use the function name. You use the arguments object.
arguments object acts like an array, so arguments[0] returns the first argument passed to the function.
arguments.length
// a property of the arguments object that tells you how many arguments the function has
arguments.caller
// reference to the function that invoked the current function.
arguments.callee() will call the function recursively. Its a reference to the currently executing function.
Is that what you mean?
Use arguments.callee.caller
It seems that the reason this works is because arguments.callee is giving you a reference to the function that is currently executing, and then arguments.caller is referencing the function that invoked that function (which is actually the same function). Maybe that is why using arguments.caller is not advisable.

context to use call and apply in Javascript?

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]

JavaScript Binding

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

Categories

Resources