Background: I am building a webapp that makes use of JQuery and the Facebook Javascript API. Since some users don't like Facebook, I have also built a thunking layer that emulates the necessary identity APIs for users who prefer not to use Facebook. To keep things clean and avoid code duplication, I have organized my Javascript code into a few classes.
Both Facebook and JQuery APIs make extensive use of callbacks. Since all of my functions are bound into objects, I found that I am using the following pattern frequently:
var obj_ref = this;
some_jquery_function_that_takes_a_callback(/* various args */,
function() { obj_ref.my_callback_method(); });
For readability, the obj in obj_ref is actually the name of the class.
Is there some nifty Javascript magic that is simpler or clearer, or is this as good as it gets?
Update: Some good commentary so far in the answers. I should have added that my callback methods generally needs to refer to variables or functions bound to the class. If I don't need that, then the anonymous function wrapper is unnecessary.
Update2: I've selected a best answer, but you should carefully read all of the answers. Each provides some useful insight into possible solutions.
If you need your this to be your obj_ref and you can assume an update to date JavaScript (which sadly you probably can't), you could use bind to do away with the wrappers:
Creates a new function that, when called, itself calls this function in the context of the provided this value, with a given sequence of arguments preceding any provided when the new function was called.
Then you could bind your methods to your objects and this:
some_jquery_function_that_takes_a_callback(/* various args */,
function() { obj_ref.my_callback_method(); });
would be the same as:
// In some initialization pass...
obj_ref.my_callback_method = obj_ref.my_callback_method.bind(obj_ref);
// And later...
some_jquery_function_that_takes_a_callback(/* various args */,
obj_ref.my_callback_method);
Then this would be obj_ref when my_callback_method is called.
Alternatively, you could pull in Underscore.js and use its bind or bindAll. You could always grab just bind or bindAll out of Underscore.js if you didn't want the whole thing.
Or, since you have jQuery in play already, you could use $.proxy in place of the standard bind:
Takes a function and returns a new one that will always have a particular context.
So you could do it like this:
// In some initialization pass...
obj_ref.my_callback_method = $.proxy(obj_ref.my_callback_method.bind, obj_ref);
// And later...
some_jquery_function_that_takes_a_callback(/* various args */,
obj_ref.my_callback_method);
Thanks to dsfq for reminding me about jQuery's version of bind.
Better to use binding to the your object to preserve invocation context:
var objRef = this;
// #1. In this case you will have wrong context inside myCallbackMethod
// often it's not what you want. e.g. you won't be able to call another objRef methods
someJqueryFunction(a, b, objRef.myCallbackMethod);
// #2. Proper way - using proxy (bind) function
someJqueryFunction(a, b, $.proxy(objRef.myCallbackMethod, objRef));
I have the same problem with callbacks. Here's how I've dealt with it.
Just like dfsq said, $.proxy does the job for you. You don't need any extra library like underscore.
Underscore js has it's own bind function which is like the $.proxy.
Apply and call (the javascript methods that can be called on functions) work great.
Let's say I have a object :
var Dog = {
name : "Wolfy",
bark : function(){
console.debug(this.name," barks!");
}
}
var AnotherDog = {
name : "Fang"
}
Dog.bark.call(AnotherDog); //--> Fang barks!
Dog.bark(); //--> Wolfy barks!
When you write your "classes", you could use this pattern to handle the invocation of callbacks.
In case you're not sure what proxy or bind do, they do something similar to this:
var Dog = {
name : "Wolfy",
bark : function(){
console.debug(this.name," barks!");
}
}
Dog.bark = funciton(){
var scope = Dog;
return Dog.bark.apply(scope,arguments);
}
Rewrites the bark function by wrapping it in a new functions which returns the result of the original function, but forces a specific scope to be used.
I usually only wrap the callback in a function when I have to pass in extra parameters:
var x = 42;
jQuery_something({}, function(y, z) { obj_ref.callback(x, y, z) });
And that is because you don't control the arguments passed into the callback yourself. But this is only if you need a reference to some var in the scope. And in some cases this means you will have to create a closure to capture the var, e.g. in a loop.
But if that's not the case, then I just pass in a reference to the function directly:
jQuery_something({}, obj_ref.callback);
Even this should work fine, since the callback reference is in scope in this particular example (so no need to copy it to obj_ref first:
jQuery_something({}, this.callback);
Obviously, the last example is about as simple and clean as it gets: "the callback argument for the jQuery method is this object's method named 'callback'"
Yes, this is quite correct. You can have a helper function which implements the pattern though to save some code.
Related
Today while working my mind was stack at some point in javascript.
I want to know that what is basic difference between
function FunctionName(){
//Code goes here;
}
And
var MyFuncCollection = new Object();
MyFuncCollection.FunctionName = function(){
//Code goes here;
}
Both are working same. Then what is difference between then. Is there any advantage to use function with object name?
I have read Question. But it uses variable and assign function specific variable. I want to create object and assign multiple function in single object.
The first one defines a global function name. If you load two libraries, and they both try to define FunctionName, they'll conflict with each other. You'll only get the one that was defined last.
The second one just has a single global variable, MyFuncCollection. All the functions are defined as properties within that variable. So if you have two collections that try to define the same function name, one will be FuncCollection1.FunctionName, the other will be FuncCollection2.FunctionName, and there won't be any conflict.
The only conflict would be if two collections both tried to use the same name for the collection itself, which is less likely. But this isn't totally unheard of: there are a few libraries that try to use $ as their main identifier. jQuery is the most prominent, and it provides jQuery.noConflict() to remove its $ binding and revert to the previous binding.
The short answer is, the method in object context uses the Parent Objects Context, while the "global" function has its own object context.
The long answer involves the general object-oriented approach of JavaScript, though everything in JavaScript is an object you may also create arrays with this Method.
I can't really tell you why, but in my experience the best function definition is neither of the top mentioned, but:
var myFunction = function(){};
It is possible to assign function to variables, and you may even write a definition like this:
MyObject.myMethod = function(){};
For further reading there are various online Textbooks which can give you more and deeper Information about this topic.
One main advantage I always find is cleaner code with less chance of overwriting functions. However it is much more than that.
Your scope changes completely inside the object. Consider the following code ::
Function:
function FunctionName(){
return this;
}
FunctionName()
Returns:
Window {top: Window, location: Location, document: document, window: Window, external: Object…}
Object:
var MyFuncCollection = new Object();
MyFuncCollection.FunctionName = function(){
return this;
}
MyFuncCollection.FunctionName()
Returns:
Object {}
This leads to some nice ability to daisy chain functions, amongst other things.
The first:
function functionName (){
//Code goes here;
}
Is a function declaration. It defines a function object in the context it's written in.
Notice: this doesn't have to be the global context and it doesn't say anything about the value of this inside it when it's invoked. More about scopes in JavaScript.
Second note: in most style guides functions are declared with a capitalized name only if it's a constructor.
The second:
var myFuncCollection = {};
myFuncCollection.functionName = function () {
//Code goes here;
};
notice: don't use the new Object() syntax, it's considered bad practice to use new with anything other then function constructors. Use the literal form instead (as above).
Is a simple assignment of a function expression to a property of an Object.
Again the same notice should be stated: this says nothing about the value of this when it's invoked.
this in JavaScript is given a value when the function object is invoked, see here for details.
Of course, placing a function on an Object help avoiding naming collisions with other variables/function declarations in the same context, but this could be a local context of a function, and not necessarily the global context.
Other then these differences, from the language point of view, there's no difference whatsoever about using a bunch of function declarations or an Object with bunch of methods on it.
From a design point of view, putting methods on an Object allows you to group and/or encapsulate logic to a specific object that should contain it. This is the part of the meaning of the Object Oriented Programming paradigm.
It's also good to do that when you wish to export or simply pass all these functions to another separate module.
And that's about it (:
This is more of a general question. I have seen some answers related to it before but none gave me a clear answer.
I want to achieve an auto binding function.
example:
var someObject;
var handle = function(arg1, callback){
someObject(arg1, callback.bind(???owner of callback???))
}
var handler = new Handler();
//Calling it
handle("my arg", handler.handlerFunction);
I'm not able to control the someObject way of calling the callback as it is a third party library and it is calling my callback with a reference to itself, so I can't use this inside my prototype definitions.
I can easily achieve this by using an extra argument to the handle function sending in handler and binding to it.
Or wrapping the handler.handleFunction into an apply block, but I think it would look much better if I could just call it the way I referred to to in the codeblock.
Is it possible to find the reference to the object owning handlerFunction?
I'm using Nodejs, if that has any relevance.
Unfortunately the way you want to call it doesn't work. Here is why:
When you call handle(handler.handlerFunction) the argument you pass is a reference to a function. Any information about handler is lost there. You could do this instead:
handle("my arg", handlerFunction.bind(handler));
Or this:
handler.handlerFunction = handler.handlerFunction.bind(handler);
handle("my arg", handler.handlerFunction);
There is simply nothing like that in JavaScript for some good reason.
Instead, as you already mentioned, pass in a context variable and apply your callback to it so that it runs in the owners context. This is commonly used in many frameworks etc...
Other than tricking existing functions that already implement this as something, why would you want to write a javascript function so that you need to alter its context (via .call or .apply) rather than explicitly passing the "context" as another parameter? Is there a performance benefit?
Example:
function tryIncrement(inc, context) {
context = context || this; // just so we can reuse same fn for the example
if( typeof context.val!= typeof 1|| typeof inc != typeof 1 ) return false;
context.val += inc;
return true;
}
var a = {name: 'A', val: 5}, b = {name: 'B', val: 20};
// reassign internal context
for(var i = 0, n = [1,3,"not a num",5]; i < n.length; i++) {
if( tryIncrement.call(a, n[i]) ) console.log('incremented', i, n[i], a);
else console.log('failed to increment', i, n[i], a);
}
// provide explicit context;
// could just as easily declared function so context was first param
// so it looked the same as previous implementation
for(var i = 0, n = [1,3,"not a num",5]; i < n.length; i++) {
if( tryIncrement(n[i], b) ) console.log('incremented', i, n[i], b);
else console.log('failed to increment', i, n[i], b);
}
There are many cases where you may wish to use this instead of passing an extra parameter. Consider the following function for example:
Function.prototype.async = function () {
setTimeout.bind(null, this, 0).apply(null, arguments);
};
This function allows us to defer a function call as follows:
alert.async("This will display later.");
alert("This will display first.");
You can see the demo here: http://jsfiddle.net/AjwQu/
Instead of binding the function to this we could have passed it as a parameter instead:
function async(funct) {
setTimeout.bind(null, funct, 0).apply(null, [].slice.call(arguments, 1));
}
We would use it like this now:
async(alert, "This will display later.");
alert("This will display first.");
The result is the same: http://jsfiddle.net/63dBF/
However to get the arguments we have to use [].slice.call(arguments, 1) instead. In the first example we could simply use arguments as the function was not a part of the argument list.
Everything has it's advantages and disadvantages. You just need to know what to use when. Hope this helps a bit.
Bonus: It's really easy to convert a function that uses this into a function that accepts an extra parameter and vice versa. First let's define a few utility functions:
var functProto = Function.prototype;
var bind = functProto.bind;
var bindable = bind.bind(bind);
var callable = bindable(functProto.call);
var appliable = bindable(functProto.apply);
The bindable function allows you to create a bindable version of an existing function which when called returns a new function bound to the given arguments.
The callable function allows you to create a callable version of an existing function which when called calls the existing function with the given arguments and this pointer.
The appliable function allows you to create an appliable version of an existing function which when called applies the given arguments and this pointer to the existing function.
Then given the function in the first example we can create the function in the second example as follows:
var async = callable(functProto.async);
See the demo here: http://jsfiddle.net/3dSBS/
Similarly we can convert the function in the second example into the function in the first example as follows:
Function.prototype.async = function () {
return async.apply(null, [this].concat([].slice.call(arguments)));
};
See the demo here: http://jsfiddle.net/rJQyS/
As you can see it's much easier to write a function using this and then construct the function accepting the context as a parameter from it than the other way around.
As far as I can tell the use of this isn't really any different than
another parameter, it just has a more complicated way of being
modified.
I think the easiest way to answer your question is to imagine if the creator of the base Javascript language had followed your conventions.
A world without this
A world without this is a scary noisy place with lots of excessive duplication:
var arr = [1,2,3,4];
arr.reverse(arr); //4321
More opportunities for misleading or verbose syntax
var str = "stringtobesplit";
"abiglongstringnotbeingsplit".split(str,":");
String.prototype.split(str,":");
And its not at all rid of apply at least:
Math.max.apply(arr); //didn't add the initial `this` since it doesn't exist
Effectively there would be a choice between creating only global functions, or creating functions on prototypes or objects that made assumptions about the types of the arguments it was receiving but didn't enforce those assumptions. For instance imagine the toString method in our fantasy world.
You could either create a global toString method which would take in an object of every type ever, and try to make them all work, or you could have a function on the prototypes of each type as it works currently, with no enforcement that it would be called on that type. Someone could call
Array.prototype.toString(str)
And we would need to handle it gracefully (for what its worth doing this with apply seems to revert to the Object.prototype.toString and returns [Object String]). So we would need to identify the correct prototype method to call in those cases, which means my guess is that the convention would be to call
str.toString(str)
or something along those lines.
So whats the point?
this is built to handle the common case for javascript methods on the prototype chain. It gives us a shorthand to allow an object to act on itself without duplicating the call to it or having to know exactly what its prototype is. Without it, we would either have to have no functions on objects, or would have to explicitly call the function on itself every time, introducing extra syntax and potential errors.
call and apply are the exception cases, and apply at least would have uses even if this went away. Its never a good idea to write your apis to the exception cases. If you're creating object oriented code, you should use this as an easy way to refer to the object that is the context for the call. If you write this well, then call and apply should be used rarely and in special situations.
TL;DR - this was designed as part of Javascript for a reason, use it when you're creating methods on objects for more clear and understandable syntax.
When you do object oriented programming your functions WILL depend on the context and it does not make sense do provide it as a parameter, as this would deafeat the purpose of object oriented programming.
It also makes sense to provide an implicit context for callbacks. You do not have to remember the correct order of the parameters if you only need the context. You would not have to use parameters at all in that case. So instead of
function mayCallback(param1, param2, context)
you could just write
function myCallback()
and use this, if you do not need param1 and param2.
To address my main purpose -- is there a performance benefit using this over a function parameter? -- the answer seems to be no:
http://jsperf.com/function-context-vs-parameter
Although there seems to be a slight benefit (may not be significant, however) around using parameter values instead of instance (this) variables within objects.
(Please test for yourself and comment if it's different)
Regarding the purpose being addressed by the other answers: there are some neat use cases as pointed out by #Aadit, maintainability is debatably a personal preference, but like #ben336 said if you're working with Objects (and thus OOP) then this can be more useful.
The ECMAScript 5th-edition native function bind may be an interesting bridge between the two worlds, or at least a time-sucking tangent to explore.
The instance vs parameter values test referenced above may also be a good example of my point -- if you're building a static library of functionality, you can "hijack" obj.callback2 by scoping to a different this, or just call obj.callback directly on your alternate context.
I study JavaScript Proxy Pattern, but I still do not get, where I can benefit from it. I would therefore like to provide you with two examples and kindly ask you to point at the difference between them.
Please, take a look at the code below:
What is the difference between the two addEventListener calls? One of them calls handleDrop in regular way. The other uses Proxy Pattern.
What will I gain using Proxy pattern approach?
I tested both functions, and they both call handleDrop successfully.
DndUpload.prototype.buildDropZone = function ()
{
var self = this,
this.dropZone.addEventListener('drop', function (e) { self.handleDrop.call(self, e) }, false);
this.dropZone.addEventListener('drop', self.handleDrop, false);
DndUpload.prototype.handleDrop = function (e)
{
alert("test");
...
};
}
You can provide me with good reference which contains very clear explanation of Proxy Pattern in JavaScript.
So what you're describing in your example isn't so much a demonstration of the Proxy pattern as much as a demonstration of confusion regarding the "calling object" and how it works in JavaScript.
In JavaScript, functions are "first-class." This essentially means that functions are data just like any other data. So let's consider the following situation:
var fn = (function () { return this.x; }),
a = {
x : 1,
fn : fn,
},
x = 2,
nothing = (function (z) { return z; });
So, we have an object a, which has two properties: fn and x. We also have variables x, fn (which is a function returning this.x), and nothing (which returns whatever it gets passed).
If we evaluate a.x, we get 1. If we evaluate x, we get 2. Pretty simple, eh? Now, if we evaluate nothing(a.x), then we get 1. That's also very simple. But it's important to realize that the value 1 associated with the property a.x is not in any way connected to the object a. It exists independently and can be passed around simply as a value.
In JavaScript, functions work the same way. Functions that are properties (often called "methods") can be passed as simple references. However, in doing so, they can become disconnected from their object. This becomes important when you use the this keyword inside a function.
The this keyword references the "calling object." That's the object that is associated with a function when that function is evaluated. There are three basic ways to set the calling object for a function:
If the function is called using the dot operator (e.g. a.fn()), the relevant object (in the example, a) is set as the calling object.
If the function is called using the function's call or apply properties, then you can explicitly set the calling object (we'll see why this is useful in a second).
If no calling object is set through method 1 or method 2, the global object is used (in a browser, this is typically called window).
So, back to our code. If we call a.fn(), it will evaluate as 1. That's expected because the this keyword in the function will be set to a due to the use of the dot operator. However, if we call simply fn(), it will return 2 because it is referencing the x property of the global object (meaning our global x is used).
Now, here's where things get tricky. What if you called: nothing(a.fn)()? You might be surprised that the result is 2. This is because passing a.fn into nothing() passes a reference to fn, but does not retain the calling object!
This is the same concept as what's going on in your coding example. If your function handleDrop were to use the this keyword, you would find it has a different value depending on which handler form you use. This is because in your second example, you're passing a reference to handleDrop, but as with our nothing(a.fn)() example, by the time it gets called, the calling object reference is lost.
So let's add something else to the puzzle:
var b = {
x : 3
};
You'll note that while b has an x property (and therefore satisfies the requirements for fn's use of this), it doesn't have a property referencing fn. So if we wanted to call the fn function with its this set to b, it might seem we need to add a new property to b. But instead we can use the aforementioned apply method on fn to explicitly set b as the calling object:
fn.apply(b); //is 3
This can be used to "permanently" bind a calling object to a function by creating a new function "wrapper." It's not really permanently binding, it's just creating a new function that calls the old function with the desired calling object. Such a tool is often written like so:
Function.prototype.bind = function (obj) {
var self = this;
return function() {
return self.apply(obj, arguments);
};
};
So after executing that code, we could do the following:
nothing(a.fn.bind(a))(); //is 1.
It's nothing tricky. In fact, the bind() property is built into ES5 and works pretty much like the simple code above. And our bind code is actually a really complicated way to do something that we can do more simply. Since a has fn as a property, we can use the dot operator to call it directly. We can skip all the confusing use of call and apply. We just need to make sure when the function gets called, it gets called using the dot operator. We can see how to do it above, but in practice, it's far simpler and more intuitive:
nothing(function () { return a.fn(); })(); //is 1
Once you have an understanding of how data references can be stored in closure scope, how functions are first-class objects, and how the calling object works, this all becomes very simple to understand and reasonably intuitive.
As for "proxies," those also exploit the same concepts to hook into functions. So, let's say that you wanted to count the number of times a.fn gets called. You can do that by inserting a proxy, like so (making use of some concepts from our bind code from above):
var numCalls = (function () {
var calls = 0, target = a.fn;
a.fn = (function () {
calls++;
return target.apply(a, arguments);
});
return (function () {
return calls;
});
}());
So now, whenever you call numCalls(), it will return the number of times a.fn() was called without actually modifying the functionality of a.fn! which is pretty cool. However, you must keep in mind that you did change the function referenced by a.fn, so looking way back to the beginning of our code, you'll notice that a.fn is no longer the same as fn and can't be used interchangeably anymore. But the reasons should now be pretty obvious!
I know that was basically a week of JavaScript education in a couple pages of text, but that's about as simple as it gets. Once you understand the concepts, the functionality, usefulness, and power of many JavaScript patterns become very simple to understand.
Hope that made things clearer!
UPDATE: Thanks to #pimvdb for pointing out my unnecessary use of [].slice.call(arguments, 0). I have removed it because it's, well, unnecessary.
Basically, passing self.handleDrop directly is functionally equivalent to passing the following function:
function() {
return self.handleDrop.apply(this, arguments);
}
because everything is passed through to the original function:
The this value
The arguments
The return value
With this in mind, compare your functions as follows:
function(e) { self.handleDrop.call(self, e) }
function() { return self.handleDrop.apply(this, arguments); }
The difference with your proxy way is:
It doesn't pass the return value through.
It doesn't pass all arguments through (only the first, e)
It doesn't pass the this value through, but uses a predefined one: self.
Now, the first two items don't make a difference here, because addEventListener doesn't care about the return value, and it also only passes one argument anyway.
But the third item is important: it sets a different this value in the function. By default, this is the element you bind the event to (it it set by the browser). Using the proxy way, you can set another this value.
Now, in your snippet it is not fully clear why you're setting a prototype function each time buildDropZone is called. Usually you define prototype functions only once. But when your handler handleDrop is called using the proxy way, this refers to the DndUpload instance, which is consistent with prototype functions in general.
Consider the code below:
function printThis() {
console.log(this);
}
var someObject = {
performTest : function() {
var self = this;
someOtherObject.higherOrderFunction(printThis);
someOtherObject.higherOrderFunction(function(){printThis.call(self)});
}
}
var someOtherObject = {
higherOrderFunction : function(f) {
f();
}
}
What will someOtherObject.higherOrderFunction(printThis) return?
How about someOtherObject.higherOrderFunction(function(){printThis.call(self)})
The answer to the first question depends on who and how you call someObject.performTest(). If I just call someObject.performTest() from a global context, it will probably print Window.
The second one will always print the someObject instance no matter what.
The closures or 'proxy pattern' as you call it comes in handy when you want to control exactly the execution context of a function.
Note: this in javascript does not behave like it does in other languages(in Java for example).
I want to delegate some function calls from one object to another:
objA.feature = objA.component.feature;
(Assuming feature is supposed to be a function both in objA and in its component)
But that clearly doesn't work, because the reference to this gets stripped from the function and ends up being a completely different object when it gets called (it actually is objA instead of objB.component).
You need to write something like this in order to get it to work:
objA.feature = function() {
objA.component.feature.apply(objA.component, arguments);
};
Is there a shorter (idiomatic) way to do that?
There's a function called "bind" on the Function prototype in newer runtimes:
var newFunc = someFunc.bind(somethingThatShouldBeThis);
will make this refer to "somethingThatShouldBeThis" when "newFunc" is called.
You can steal code from something like the Functional library to provide a "bind" function in environments that lack a native one.
edit — here's the code from Functional:
Function.prototype.bind = function(object/*, args...*/) {
var fn = this;
var args = Array.slice(arguments, 1);
return function() {
return fn.apply(object, args.concat(Array.slice(arguments, 0)));
}
}
Pretty simple, eh? It just returns a function back to you that, when invoked, will call the first argument as a function, and also pass along whatever arguments you pass in to the result (that is, to "newFunc" in the example above). The main wrinkle is that this one also saves extra arguments passed in originally, which can sometimes be handy.
Here is a great article on scope:
Binding Scope in JavaScript
However, most JavaScript frameworks (MooTools, jQuery) have built in methods for this. jQuery uses "proxy" and MooTools uses "bind", so be sure to check the documentation of whatever framework you're using.
Your best bet is to use a createDelegate-style method like some of the frameworks do. A bare-bones implementation was posted on OdeToCode a few years ago.