.call() / .apply() with NO parameters VS simply calling a function with () parenthesis - javascript

I've seen it done differently in code out there, but is there any benefit or reason to doing a (blank params) .call / .apply over a regular () function execution.
This of course is an over-simplified example
var func = function () { /* do whatever */ };
func.call();
func.apply();
VERSUS just the simple parenthesis.
func();
Haven't seen any information on this anywhere, I know why call/apply are used when params are passed.

When you call a method with func();, this variable inside the method points to window object.
Where as when you use call(...)/apply(...) the first parameter passed to the method call becomes this inside the method. If you are not passing any arguments/pass null or undefined then this will become global object in non strict mode.

Yes, there is an important difference in some cases. For example, dealing with callbacks. Let's assume you have a class with constructor that accepts callback parameter and stores it under this.callback. Later, when this callback is invoked via this.callback(), suddenly the foreign code gets the reference to your object via this. It is not always desirable, and it is better/safer to use this.callback.call() in such case.
That way, the foreign code will get undefined as this and won't try to modify your object by accident. And properly written callback won't be affected by this usage of call() anyways, since they would supply the callback defined as an arrow function or as bound function (via .bind()). In both such cases, the callback will have its own, proper this, unaffected by call(), since arrow and bound functions just ignore the value, set by apply()/call().

Related

In js when returning a reference to a this value vs passing the this reference keyword, is there a difference in binding time?

I'm trying to understand the below code which prevents bugs caused by a function silently passing to a call back function more arguments that aren't wanted in the parameters of the callback function:
["1","2","3"].map(parseInt)
returns [1, NaN, NaN] because the index gets passed as a second parameter to parseInt which accepts it as the radix, so the array values are invalid. To solve it, the author of this blog post suggests a js extension:
Function.prototype.only = function(numberOfArgs) {
var self = this; //the original function
return function() {
return self.apply(this,[].slice.call(arguments,0,numberOfArgs))
}
};
Which would be called like so:
["1","2","3"].map(parseInt.only(1))
I'm struggling to understand why "this" is passed as a function parameter while self is returned as a reference to this. They both point to parseInt correct? Is there a difference in binding times of parameters vs return values?
They both point to parseInt correct?
No.
The value of this depends on how a function is called.
The function passed to map gets called by the internals of map.
Look at the documentation for map.
If a thisArg parameter is provided to map, it will be used as callback's this value. Otherwise, the value undefined will be used as its this value.
So if the returned anonymous function used this instead of self it would be calling undefined.apply not parseInt.apply.
I'm struggling to understand why "this" is passed as a function parameter while self is passed as a reference to this. They both point to parseInt correct?
No. self will refer to parseInt. this will be whatever this the function was called with, which could be anything. In your example:
["1","2","3"].map(parseInt.only(1))
...this will either be a reference to the global object (in loose mode) or undefined (in strict mode), because map will use undefined when calling the callback (which is turned into a reference to the global object in loose mode).
There are several ways this might be something else though:
If a second argument were passed to map:
["1","2","3"].map(parseInt.only(1), {})
// Second argument -----------------^^
...it would use that value rather than undefined when calling the callback.
If Function#bind were used on the function only returns:
["1","2","3"].map(parseInt.only(1).bind({}))
// Bind ---------------------------^
...then this would be that value.
If the function only returns were called with call or apply (which is what map does, so this is kind of a repetition of #1 :-) ), the value supplied for this would be used.

Call() usage in javascript

Javascript object which has key as function name and value as function.
var fnObj = { getReport: [Function], getAccountDetail: [Function] }
method invoke using call
fnObj['getReport'].call(null,arg1,arg2); // since its dynamic method call so using call()
or without call()
var a = fnObj['getReport'](arg1,arg2);
dynamic function
getReport:function(arg1,arg2){
//it will do some execution with arg1 and arg2
return {'some': 'result'};
}
Which way of call method invoke is correct?
The only difference between those two methods is the value of this inside the function.
When you explicitly set it to null it will be null (unless you aren't in strict mode, in which case it will be the default object), when you don't it will be the value of fnObj.
Which is correct (assuming that one is not) will depend on what the function does with this (which we can't tell because you haven't shared that code).
Re update:
Since you don't use this in the functions, it doesn't make a difference (except that using call is more long-winded and implies that the value of this matters when a maintainer comes along to read the code).
The normal way would be.
fnObj.getReport(arg1, arg2);
Unless you have specific needs.

Why 'this' points to window inside a function when apply() or call() is being called?

I'm reading Nicholas Z.Zakas' Professional JavaScript for web developer 3rd edition and inside the Reference types chapter I got a bit confused at the function type part.
function sum(num1, num2){
return num1 + num2;
}
function callSum1(num1, num2){
return sum.apply(this, arguments);
}
alert(callSum1(10,10)); //20
He says:
"In this example, callSum1() executes the sum() method, passing in this as the this value (which is equal to window because it's being called in the global scope) and also passing in the arguments object."
I understand what he says, but I don't understand the why. This supposed to point to the function doesn't it? Now I'm confused that it's pointing to the window because it's being called in the global scope ..
Can someone be kind to explain it to me? :)
I'm not sure if I will or I have to use this technique later, but I want to make sure I understand it, especially the this part. More details about this and its usage will come in the OOP section, but it's now an interesting question.
Thanks in advance!
The value of this depends on how you call a function.
If you call a function using call or apply then the value of this will be the first argument to that function.
Here you have sum.apply(this, arguments); so it will pass the current value through. As usual, that value is determined by how you call the function.
Since you call callSum1(10,10) with no context, this will be window.
(If you were in strict mode, it would be undefined. If you weren't in a browser, it would be whatever the default object of the JS environment you were using was).
Here:
alert(callSum1(10,10)); //20
...you're calling callSum without doing anything to set this during the call, and so this is defaulted to the global object (window, on browsers). (In loose mode; in strict mode, this would have been undefined.)
Since you're then using apply and passing that same this into it:
return sum.apply(this, arguments);
...naturally the global object is also used when calling sum.
I understand what he says, but I don't understand the why. This supposed to point to the function doesn't it?
No, this almost never refers to functions. (It can, of course, it just very rarely does.)
Now I'm confused that it's pointing to the window because it's being called in the global scope ..
It's not because it's being called in the global scope; it would be the same if it were being called from inside a function. What matters isn't where the call occurs, but how. Any time you call a function without doing anything to set this, in loose mode, this during the function call will be the global object. It doesn't have to be at global scope; what matters is how you call the function.
The rule is actually a lot simpler than people make it out to be: If you call a function without doing anything to set this, during the call, this will be the global object (in loose mode) or undefined (in strict mode). Here are the things you can do to set this during a function call:
Call the function as part of an expression getting the function from a property on an object. For example, foo.bar(); retrieves a reference to the function from the bar property on foo, then calls bar. Because we did it that way, during the call to bar, this refers to foo.
Call the function using .call or .apply; this will be what you pass in the first argument. (In loose mode, if you pass undefined, null, or a non-object in the first argument, during the call this will be the global object. In strict mode, it'll be what you pass.)
Call a bound function. That's a function created via Function#bind (an ES5 feature). Bound functions have this "baked into" them.
More (on my blog):
Mythical methods
You must remember this
Under the Window object part ~20 pages later, I'm reading this: "As mentioned previously, the this value is equivalent to the Global object when a function is executed with no explicit this value specified (either by being an object method or via call()/apply())." :)
Maybe I didn't get it before, but now it's clear with his words as well. By the way, the book is awesome! Now with Math object I can understand much more the apply() method, too.
var values = [1,2,3,4,5,6];
var max = Math.max.apply(Math, values);

What's the difference between these two javascript calls?

What does the 'function' do in the following?
$('.event-row').on('mouseover',function(){
arc.event_handler.event_row_over();
});
$('.event-row').on('mouseover',arc.event_handler.event_row_over );
There's a very important difference.
The first one will call the function with the context its this value as the event_handler object.
The second one will call the function with the context its this value as the DOM element to which the handler is bound.
So the first one preserves the expected calling context this value, which may be required by the function.
In the first case with the anonymous function this inside that function is bound to the DOM element that caused the event. This is a convention that is common in browsers and also done when binding events natively. When calling arc.event_handler.event_row_over(); however, this is re-bound to arc.event_handler inside event_row_over; as it's called as an object method and in such a case this points to the object on which the method was called. The method will be called without any arguments.
In the second case you register the function arc.event_handler.event_row_over for the event. When called jQuery sets this to the related element so inside event_row_over, this points to that element. arc.event_handler is not available in there unless there is some other variable that points to it. jQuery also passes the event object as the first argument so the method is called with that argument.
Usually object methods expect this to be their object, so in almost every case you want to use the anonymous function to wrap the call. In case the element matters, pass this as an argument to the method.
Another way, without an anonymous function, would be using the bind() method every function has:
$('.event-row').on('mouseover', arc.event_handler.event_row_over.bind(arc.event_handler));
However, only modern browsers support this natively.
In the first case you are enclosing the function call in an anonymous function.
In the second case you are just assigning the function pointer..
First off, it seems like there is an extra dot in there.. arc.event_handler.event_row_over.(); should probably be just arc.event_handler.event_row_over();
And all the anonymous function does is it calls a member function named event_row_over of the arc.event_handler object; and it doesn't return anything.
The 'function' keyword will creates a new closure and encapsulate the scope. Good article on closures https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Closures.
The first case, you have an additional function wrapper. This is useful when you want to do something else before calling the real event handler 'arc.event_handler.event_row_over()' for example you may do something like below:
$('.event-row').on('mouseover',function(){
doPreEventHandling();
arc.event_handler.event_row_over();
doPostEventHandling();
});
On the other hand you may even extract that annonymous function to be a named function and call as below:
var eventHandler = function(){
doPreEventHandling();
arc.event_handler.event_row_over();
doPostEventHandling();
};
$('.event-row').on('mouseover', eventHandler);
All above will be just similar in behavior, but more wrapper functions you have more abstraction you gain. But it will compromise performance and sometimes readability.
The context/scope of the function will not be the same.
Also, with the second one,
$('.event-row').on('mouseover',arc.event_handler.event_row_over );
you're getting the event object as an argument.

What is and how to determine the calling context of an invoked method or function within another function?

What is the calling context of an invoked method or function within another function?
In browsers, the default calling context is the window object. In various situations, how do I avoid this?
If a function is invoked -- for example, by theFunction(); -- within a containing function, is the invoked function's calling context the containing function?
In these two examples
(function ()
{
something.initialize();
}());
and
(function ()
{
something.initialize.call(this);
}());
..., is the calling context the same?
They are not the same. In the following I assume you were talking about this when you mentioned context.
In the first example, inside initialize, this will refer to something. In the second one, it will refer to the global object, which is window in browsers.
What this refers to is determined by how the function was called. There are five cases:
func(), calling a function "standalone": this refers to the global object.
new func(), calling a function as constructor method: this will refer to an empty object which inherits from func.prototype.
obj.func(), calling a function as property of an object: this will refer to the object obj.
func.apply(foo), func.call(foo), invoking a function with apply or call: this refers to the object passed as first argument.
ECMAScript 5 also introduced .bind() [MDN] which enables you to bind this to a certain object, without immediately calling the function.
Now you understand why in your second example, inside initialize, this will refer to window:
The outer function is called "standalone" (first case), so this inside of it will refer to window. Next you are passing this to call, which sets this inside initialize to window (fourth case).
Further reading:
MDN - this, explains all I write above with some examples.
No, they are not the same. The first parameter to the call method sets the value of this inside that function; example 1's this should theoretically contain a reference to something; example 2's this corresponds to the this of your self executing function.
The environment available to a function when it is invoked is based on several things.
the this binding which is different for the initialize method in your example
the actual parameter bindings which are not and a binding for a special arguments object
a binding for the function name, if any
the environment chain at the time the function was created. This is the "close" part of the term "closure". A javascript function "closes over" all the variables that are in-scope when the function object comes into existence.
In your example, only 1 is affected by the choice to use call which has the effect of passing this instead of something as the this value in the method body.
The relevant part of the spec starts at section 10.4.3
The following steps are performed when control enters the execution context for function code contained in function object F, a caller provided thisArg, and a caller provided argumentsList: ...
Functions don't create context, unless it's a constructor (a function called with new).
In your second example the context is undefined (which gets transformed into the global object , window). In ES5 strict mode it won't be transformed into anything.
I recommend John Resig's interactive JavaScript tutorial on the topic of context.

Categories