On Execution context of anonymous functions and call/apply/bind - javascript

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);
}

Related

What's the advantage of using `var self = this` in knockout.js view models [duplicate]

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

why is it necessary to wrap function call in a function body

I often see something like the following in JavaScript:
$("#sendButton").click(function() {
sendForm();
}
Why is it necessary to wrap the call to sendForm() inside a function? I would think that doing it like this would be more readable and less typing.
$("#sendButton").click(sendForm);
What are the advantages/disadvantages to each approach? thanks!
There's typically two cases where you'd want to use the former over the latter:
If you need to do any post-processing to the arguments before calling your function.
If you're calling a method on an object, the scope (this reference) will be different if you use the second form
For example:
MyClass = function(){
this.baz = 1;
};
MyClass.prototype.handle = function(){
console.log(this.baz);
};
var o = new MyClass();
$('#foo').click(o.handle);
$('#foo').click(function(){
o.handle();
});
Console output:
undefined
1
Probably one too many answers by now, but the difference between the two is the value of this, namely the scope, entering sendForm. (Also different will be the arguments.) Let me explain.
According to the JavaScript specification, calling a function like this: sendForm(); invokes the function with no context object. This is a JavaScript given.
However, when you pass a function as an argument, like this: $(...).click(sendForm), you simply pass a reference to the function for later invocation. You are not invoking that function just yet, but simply passing it around just like an object reference. You only invoke functions if the () follows them (with the exception of call and apply, discussed later). In any case, if and when someone eventually calls this function, that someone can choose what scope to call the function with.
In our case, that someone is jQuery. When you pass your function into $(...).click(), jQuery will later invoke the function and set the scope (this) to the HTML element target of the click event. You can try it: $(...).click(function() { alert(this); });, will get you a string representing a HTML element.
So if you give jQuery a reference to an anonymous function that says sendForm(), jQuery will set the scope when calling that function, and that function will then call sendForm without scope. In essence, it will clear the this. Try it: $(...).click(function() { (function() { alert(this); })(); });. Here, we have an anonymous function calling an anonymous function. We need the parentheses around the inner anonymous function so that the () applies to the function.
If instead you give jQuery a reference to the named function sendForm, jQuery will invoke this function directly and give it the scope that it promises to always give.
So the answer to your question becomes more obvious now: if you need this to point to the element target of the click when you start work in sendForm, use .click(sendForm). Otherwise, both work just as well. You probably don't need this, so skip the anonymous function.
For those curious, scope can be forced by using the JavaScript standard apply or call (see this for differences between the two). Scope is also assigned when using the dot operator, like in: obj.func, which asks of JavaScript to call a function with this pointing to obj. (So in theory you could force obj to be the scope when calling a function by doing something like: obj.foo = (reference to function); obj.foo(); delete obj.foo; but this is a pretty ugly way of using apply.
Function apply, used by jQuery to call your click handler with scope, can also force arguments on the function call, and in fact jQuery does pass arguments to its click handlers. Therefore, there is another difference between the two cases: arguments, not only scope, get lost when you call sendForm from an anonymous function and pass no parameters.
Here you are defining an anonymous event handler that could call multiple functions inline. It's dirty and tough to debug, but people do it because they are lazy and they can.
It would also work like your second example (how I define event handlers):
$("#sendButton").click(sendForm)
Something you get by defining your event handlers inline is the ability to pass event data to multiple functions and you get this scoped to the event object:
$("#sendButton").click(function(event) {
sendForm();
doSomethingElse(event);
andAnotherThing(event);
// say #sendButton is an image or has some data attributes
var myButtonSrc = $(this).attr("src");
var myData = $(this).data("someData");
});
If all you are doing is calling sendForm, then there isn't much difference, in the end, between the two examples you included.
$("#sendButton").click(function(event) {
if(event.someProperty) { /* ... */ }
else { sendForm({data: event.target, important: 'yes'}); }
}
However, in the above case, we could handle arguments passed to the callback from click(), but if the sendForm function is already equipped to handle this, then there's no reason why you wouldn't place sendForm as the callback argument if that is truly all you are doing.
function sendForm(event) {
// Do something meaningful here.
}
$("#sendButton").click(sendForm);
Note that it is up to you where you handle the differing layers of logic in your program; you may have encapsulated certain generic functionality in a sendForm function then have a sendFormCallback which you pass to these sorts of function which handle the interim business of event/callback processing before calling sendForm itself.
If you are working in a callback-heavy environment, it would be wise to separate significant functionality from the callback triggers themselves to avoid callback hell and promote maintainability and readability in your source code.
It's just to lock scope. When you wrap that sendForm() in the anonymous function that closes over the current scope. In other words, the this will be kept with it. If you just pass sendForm then any calls to this will come from the calling scope.
This is a good question for learning about scope in javascript, and questioning conventions.
Nope, that second example is perfectly valid.
99.9% of jQuery examples use the first notation, that doesn't mean you need to forget basic JavaScript syntax.

JavaScript Code Architecture - Use Constructor Functions Or Not

Please help me decide whether I should use a function's prototype object and the "new" keyword or completely stay away from constructor functions.
Situation:
Function called widget() that will be called 10-15 times to initialize each widget on the page. widget() contains quite a few internal methods.
Each time widget() is called, the function needs to return an object that acts as an API to operate on the widget.
Question
1) Do I put all the internal methods inside Widget() under its prototype property? It does not make sense but the main reason for this is to not re-instantiate the internal functions every time widget() is called.
But if I do put the internal functions in prototype, each instantiated w object (w = new Widget();) has access to internal private methods.
2) If I stay away from constructor functions and new keyword and structure my code as down below, how do I fix the performance concern of the internal functions getting re-instantiated every time widget() is called.
function widget()
{
var returnObj = {};
/* Add internal functions but this will be re-instantiated every time */
return returnObj;
}
You have a bit of a tradeoff here. As you seem to already understand, methods you put on the .prototype are publicly available, but that is the most efficient places to put methods as they are automatically added to all new copies of that object in a very efficient manner. When using .prototype for methods, there is only one copy of your methods and a reference to that single copy is automatically added to all new instantiations of that object.
But, javascript doesn't have private methods built-in and the only work-around for that involves not using the .prototype for them or for any methods that need to call the private methods.
This article by Doug Crockford is a pretty good description of how you can create privacy for either data or methods in any object.
In either case, I don't see any reason to avoid using the new keyword to create new objects. You can make either .prototype or private methods work with new.
But, if you want to achieve truly private methods, then you can't use .prototype for either the private methods or any methods that need to access them so you have to decide which is more important to you. There is no single correct answer because your need for privacy is situation-specific.
In my coding, I generally don't enforce privacy and I do use .prototype and new. I designate "non-public" methods on the prototype by starting their name with an underscore. This is a notational convention, not an access enforcement scheme.
In answer to your second question about avoiding the new operator and reinstantiating methods, I'd just ask why you're doing this? What are you gaining? I'm not aware of any downsides to using new. As best I understand your decision about whether to use .prototype vs. manually create/assign methods in your constructor should be about the need for private methods.
FYI, 15 objects is hardly going to create a significant difference in performance either way here. I would evaluate your need for true privacy and make your decision based on that. If you HAVE to enforce privacy, then go with the Crockford method for implementing private methods. If you don't HAVE to have true privacy, then use .prototype. I don't see a reason here to avoid using new in either case.
You can use a metaconstructor* pattern to get around this.
function defineCtor(metaCtor) {
var proto = new metaCtor();
var ctor = proto.hasOwnProperty('constructor') ?
proto.constructor : new Function();
return (ctor.prototype = proto).constructor = ctor;
}
Now you have a function that constructs constructors (or more accurately constructs prototypes and returns constructors).
var Widget = defineCtor(function() {
function doInternalStuff() {
// ...cant see me
}
// this function ends up on the prototype
this.getFoo = function() { return doInternalStuff(); };
});
// ...
var myWidget = new Widget();
Explanation
defineCtor takes a single anonymous function as a property. It invokes the function with new, creating an object. It assigns the object as the prototype property of a new constructor function (either an empty function, or the generated prototype object's own constructor property), and returns that function.
This provides a closure for your internal functions, addressing your question 1, and sets up the constructor/prototype pair for you, addressing question 2.
Comparison
Compare the defineCtor technique to the following two examples.
This example uses the prototype, and has problem 1: the internal stuff is not encapsulated.
function Widget(options) {
this.options = options;
}
Widget.prototype = {
getFoo: function() {
return doInternalStuff();
}
};
// How to encapsulate this?
function doInternalStuff() { /* ... */ }
This example sets up everything in a constructor, and has problem 2: each time it constructs an object, it instantiates new function objects for each property.
function Widget(options) {
this.options = options;
function doInternalStuff() { /* ... */ }
this.getFoo = function() {
return doInternalStuff();
};
}
This example uses the technique described above to provide encapsulation while still leveraging the prototype:
var Widget = defineCtor(function() {
// ^
// This function runs once, constructing the prototype.
// In here, `this` refers to the prototype.
// The real constructor.
this.constructor = function(options) {
// In function properties, `this` is an object instance
// with the outer `this` in its prototype chain.
this.options = options;
};
function doInternalStuff() { /* ... */ }
this.getFoo = function() { return doInternalStuff(); };
});
// ...
var myWidget = new Widget();
This approach has a few benefits, some more immediately obvious than others.
It provides encapsulation. You could do this by wrapping the first "comparison" example in an immediately invoked function, but this approach may be cleaner and more easily "enforced" in a team setting.
It's extensible. You can give your "metaconstructor" functions their own prototypes, with function properties like "extends", "mixin", etc. Then, inside the body of metaCtor, you can write things like this.extends(BaseWidget). The defineCtor API never needs to change for any of this to happen.
It "tricks" Google Closure Compiler, Eclipse, jsdoc, etc. into thinking you are defining the actual constructor function rather than a "meta function." This can be useful in certain situations (the code is "self-documented" in a way these tools understand).
* As far as I know, the word "metaconstructor" is completely made up.

Naming: createFunctionDelegate() vs createDelegateFunction()?

It appears that I am not able to choose between two names for a function:
createFunctionDelegate() and createDelegateFunction().
If it matters, the purpose of the function is that it creates a new function that calls the supplied callback function in the context of the second argument. For example:
var foo = {
init: function() {
setTimeout(App.createFunctionDelegate(this.method, this));
},
method: function() {}
}
When foo.init() is run, it sets a timeout that calls a function which delegates the execution to another function (this.method) called in the context of this (foo).
Anyway, I am not sure which way I should name this function. This is important to me, because I am going to use it in hundreds of places and sometimes I type the one and occasionally the other one. This has to change, I have to choose.
I would use neither of these. What you want to do will be offered by bind() in ES5. I would define Function.prototype.bind if it does not exist already, as described here (but read the description and the possible drawbacks carfully).
This way you make sure you use native functionality if it is supported.
What about just createDelegate(this.method, this)?
As a side note, other places where I've seen this kind of method (and written them), the param ordering is context, function, so createDelegate(this, this.method)

Javascript question: Problem with calling an objects methods

Say I have an object called FieldEdit. I define the function constructor for this object, instantiate it via. var obj = new FieldEdit(), and define its methods by FieldEdit.prototype.<method name> = function() { ... }.
Under what situations would calling this object's methods within the objects' other methods (via. this.<method name>();) fail?
Note that I want to avoid posting a code sample for this if I can since I think this is simply a problem with my understanding of Javascript more than anything, really. I'm pretty sure my code is sound, to the best of my knowledge (and it's my knowledge that's the question here, besides).
The most likely scenario where this would reference an object other than FieldEdit during execution of FieldEdit methods is within a nested scope like a closure, an event handler, or any function or method called explicitly with .call(someOtherScope) or .apply(someOtherScope, args).
You can work around that, of course, by maintaining a variable reference to the FieldEdit instance and using FieldEditInstance.<method>() instead.
PrototypeJS allows you to wrap functions with Function.bind for this purpose, but it's easily accomplished otherwise, either with:
var FieldEditInstance = this;
obj.methodThatUsesACallback(function() {
// use that instead of this
});
OR
var FieldEditInstance = this;
var callback = function() {
// ...
};
// This is more or less what PrototypeJS' Function.bind produces
var boundCallback = function() {
return callback.apply(FieldEditInstance, arguments);
};
obj.methodThatUsesACallback(boundCallback);

Categories

Resources