Following this melonJS tutorial, I'm stumped by a couple ways this callback is used (Scroll down to Part 2: Loading our level, you will see complete code)
// Set a callback to run when loading is complete.
me.loader.onload = this.loaded.bind(this);
I read this tutorial on callbacks, so I understand what they're used for... But I don't understand. It says this.loaded.bind(this)
1) What is the difference between this first and second this statements
2) what does doing bind and passing in (this) do?
Thank you
.bind(this) sets the context of the function
If you only set it to this.loaded, the context is not preserved
This might make a little more sense
var cntx = this;
me.loader.onload = function() {
cntx.loaded();
}
However, in this example, no arguments are passed to the loaded function. By using the bind one-liner, you preserve context, and you don't have to worry about any arguments being dropped along the way.
Read about Function.prototype.bind here
Related
I am learning JavaScript and becoming confused by the logic of the code examples. From codecademy. Why are there function set-ups in function calls?
I'm quite confused. I am moving from a simplified C-like langue.
The JavaScript example
var main = function(){
$('.article').click(function(){
$('.description').hide();
$(this).children('.description').show();
});
};
My understanding:
- main is a function name with a return type of var.
$('.article') is a element/object/or class object.
.click() is a call to a member function
But:
???:
.click(function(){
$('.description').hide();
$(this).children('.description').show();
});
This seems to be a newly on the spot created function to run When/If click() is activated or run.
The way I used to think is like this:
var *p_obj = $('.article');
var *p_obj = $('.description');
var do_click()
{
p_obj2.hide();
p_obj.children(p_obj2).show();
}
var main(){
p_obj.click(do_click);
}
Function main() looks at p_obj and calls click().
Click() evaluates to true/false and run the pointer_to function do_click().
Function do_click() looks at the p_obj2 and calls hide(), which performs an action of hiding the p_obj2.
Function do_click() also looks at p_obj and uses children to scope focus to p_obj2, then it runs show(), which preforms an action of displaying p_obj2.
I do realize my C-like example is wrong and odd. I realize my terminology is wrong or otherwise used incorrectly.
The way this design looks seems like I must write extended functionality on-the-spot for every call to .click(), so if-then .click() is run on 3 different items, I'm creating different extended functionality for each object. But I would normally create a single function that varies it's internal execution based on the object or condition click() calls it by.
This set-up seems alright if the code a relatively simple or short, but on-the-spot functional seems like overworking for longer code and code where the functionality repeats but the objects change.
Am I thinking about JavaScript functions with-in functions correctly and is this a design goal of the langue to add long repeating extended functions with-in functions?
Here, you should understand 2 things:
passing functions as arguments
anonymous functions
The first concept is particulary important because callbacks are popular in JavaScript, so let me explain it for callbacks. Imagine we have 2 functions getStuffFromWeb and processStuff. You probably expect that they are used like this:
var result = getStuffFromWeb();
processStuff(result);
But the issue here is waiting for getStuffFromWeb may take some time (the server is busy), so instead they are usually used in a "when you finish, call this function" manner, which is:
var getStuffFromWeb = function(params,callback) {
...
callback(result);
};
getStuffFromWeb(someParams,processStuff);
Well, in fact the structure of getStuffFromWeb will be different, most likely something like this:
var getStuffFromWeb = function(params,callback) {
requestObject.make_request(params)
.onSuccess(callback);
};
So when getStuffFromWeb is called, it starts to listen to response while the code after getStuffFromWeb(someParams,processStuff); goes on evaluating. When the response comes, it calls the callback function to process the data further using the procedure we have defined (processStuff).
The second concept is rather simple: you may of'course write smth like
var processStuff = function() {...};
var getStuffFromWeb = function(params,callback) {
requestObject.make_request(params)
.onSuccess(callback);
};
getStuffFromWeb(someParams,processStuff);
but if you use processStuff only once, why define a named function? Instead, you can just put the very same expression inside the onSuccess param like this:
var getStuffFromWeb = function(params) {
requestObject.make_request(params)
.onSuccess(function() {...});
};
getStuffFromWeb(someParams);
This looks exactly like if we took the value of processStuff and put it directly to the onSuccess's argument (and that's called anonymous function). And also we got rid of an extra argument of getStuffFromWeb.
So basically that's it.
Simple answer is that the second argument of click() requires a callback function.
This can be a named function passed as reference as in your p_obj.click(do_click); example or it can be an anonymous function with self contained logic. Anonymous functions are very common in javascript
It's the same thing just with 2 different ways of declaring the callback.
Note that the only time you would return anything from an event handler function would be to return false which effectively prevents the default browser event (url opening from href or form submit for examples) and stops event propagating up the DOM tree
main is a function name with a return type of var.
No. main is a variable which is assigned an anonymous function. The function name would go between the keyword function and the () containing the argument list.
It has no return statement so it returns undefined.
$('.article') is a element/object/or class object.
It is a call to the function $ with one argument. The return value is a jQuery object.
.click() is a call to a member function
Pretty much. In JavaScript we call any function that is the value of a property of an object as method.
This seems to be a newly on the spot created function
function () { } is a function expression. It creates a function, exactly like the one used to assign a value to main earlier. This question is worth reading for more on the subject.
When/If click() is activated or run.
The click function is called immediately. The new function is passed as an argument.
The purpose of the click function is to bind a click event handler so that when a click event hits the element later on, it will trigger the function passed as an argument.
I do realize my c -like example is wrong and odd. I realize my terminology is wrong or otherwise used incorrectly.
Leaving aside vagaries of syntax. The main difference here is that the click event handler function is that the event handler function is stored in an intermediary variable.
You can do that in JavaScript just as easily, and then reuse the function elsewhere in the code.
var main = function(){
function show_specific_description() {
$('.description').hide();
$(this).children('.description').show();
}
$('.article').click(show_specific_description);
show_specific_description.call($(".article").last()[0]);
};
main();
is this a design goal of the langue to add long repeating extended functions with-in functions?
No. Passing a function expression as an argument is a convenient way to be more concise when you don't want to reuse the function. It's not the only way to pass functions about.
main is currently a function.
It is possible to be overwritten (even to a different type). var is not the return type, it's a statement that main is a variable.
All values should be declared as variables, within the highest scope you intend them to be used (in JS, scope typically means functions, not blocks).
You have the right idea, suspecting that the function gets passed in, and called at a later point in time (and this is actually one of the harder parts for people to get, coming from certain other languages). You'll see this behaviour all through JS.
One key thing to keep in mind in this language (you haven't hit it yet, but you will) is that JS is lexically scoped.
function getInnerX () {
var x = 5;
function getX () {
return x;
};
return getX;
}
var x = 10;
var getX = getInnerX();
console.log(getX()); // 5
The function getX inside of getInnerX has access to the references around it, at the point where it's defined (not where it's called), and thus has live access to the inner x, even if its value changes over time.
This will be another important piece of understanding what you see going on in the language, especially in the case of callbacks.
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...
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.
I have a script, that based upon specific scenarios, may need to supersede functions to do some processing before eventually calling the original function. (See "'overriding' Javascript Function")
I can get this working in general - here's a basic example using the jQuery plugin Tinyscrollbar (not my intended application, just something quick and easy to illustrate):
(function ($) {
// Snip..
function initalize() {
oSelf.update();
setEvents();
return oSelf;
}
// Snip..
function setEvents() {
(function () {
var oldInit = wheel;
wheel = function (oEvent) {
console.log('Intercept');
oldInit(oEvent);
}
})();
// Original event code, irrelevant to question
}
function wheel(oEvent) {
// Actual function, related to using the mousewheel
}
})(jQuery);
When I scroll the mousewheel, the console prints 'Intercept', and the scrollbar moves as originally defined. Wonderful!
However, the function name is hardcoded, and doesn't live in the global scope, so window[] is unavailable (which I like). Is there any possible combination of black magic, 'new Function()', and/or other way to loop through a potential list of function names (which may change based on other logic) and encapsulate them in this (or similar-in-spirit) manner?
Thanks in advance!
Unfortunately, there's no way to enumerate or dynamically access members in a scope object (with the convenient exception of the global scope/window object)
So you'd need to rephrase your code a bit. Instead of having free-floating functions in your outer function, have objects with methods on them. That'd make replacing those methods much easier.
There's some additional trickiness if you modify your functions after you started assigning them as event handlers or whatever. If you happen to use some kind of bind() wrapper around those functions, the correctness of your behavior will depend a lot on that bind() function.
Specifically, if you want the replacement method to retroactively become the method called for any event handler or callback it was assigned to, you'll want to use a bind() wrapper that takes a context object and a string meant to be the function name rather than a context object and a function reference. (and make sure that bind() doesn't resolve that string early to shave some ms on each calls.)
If don't don't want the retroactive behavior, you still have to make sure you don't have some bind()-ed version of the original method floating around and still being used for new callbacks after your replacement happened.
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.