Javascript closure VS dojo lang.hitch - javascript

Which is best practice, which results in better performance?
using closure or dojo.lang.hitch ?
Thanks

Actually lang.hitch(scope, method) returns a closure, i.e. it returns a function, which will call function method in the given scope. That's useful especially when defining callbacks in object oriented code, so you can write:
on(dom.byId("button"), "click", lang.hitch(this, "callback"));
instead of:
on(dom.byId("button"), "click", function(scope, method) {
return function() {
method.apply(scope);
}
}(this, this["callback"])); // execute the anonymous function immediately to get a closure
Something like this will work:
on(dom.byId("button"), "click", this["callback"]);
but this inside the callback method will point to the button.
See the complete code with additional details in jsFiddle: http://jsfiddle.net/phusick/r7jLr/

Related

How can you pass anonymous functions as parameters to existing functions to use later in javascript?

I am trying to create a basic javascript framework that you can pass different things into, including functions for it to execute later. Right now, I'm in a more simple testing phase, but I can't quite get the function calling to work. A piece of my code is here:
[My JS Fiddle][1]http://jsfiddle.net/mp243wm6/
My code has an object that holds different data, and I want to call the method later, but with data that is available at the time of creation. Here is a code snippet of the function that uses the function that is passed to the object:
clickMe : function() {
this.obj.click(function() {
this.func();
});
}
Any suggestions or things I should read are welcome.
The problem is that there're two different contexts:
clickMe : function() {
// here is one
this.obj.click(function() {
// here is another
this.func();
});
}
You can simple pass the function as parameter, like the following:
clickMe : function() {
this.obj.click($.proxy(this.func, this));
}
http://jsfiddle.net/mp243wm6/2/
The problem:
Considering your code in the JSFiddle, you have:
onClick : function() {
this.obj.click(function() {
this.func();
});
},
As noted, you have different contexts going on here.
Consider the snippet this.obj.click(function() { this.func(); }). The first this here is a reference to the framework.events object. The second this here is a reference to whatever will be this when this function get called. In the case of your JSFiddle, when this.func gets called, this is actually the DOM object that represents the <div id="test">TEST</div> node. Since it doesn't have a func function, calling func() on it causes:
Uncaught TypeError: undefined is not a function
You have to understand the following: you have to pass the correct this in which you want the function func to be called.
The solution:
A couple of ways to make it work as you would like:
1. with bind
this.obj.click(this.func.bind(this));
This way, you are telling: "call my this.func function, but make sure that it will be called using the this that I am passing as a parameter". Vanilla JS, no $.proxy stuff.
JSFiddle
2. with a copy of the reference to the actual function
onClick : function() {
var theFunctionReference = this.func;
this.obj.click(function() {
theFunctionReference();
});
},
This way, you will not rely on the value of this outside of the context of the framework.events object.
JSFiddle
The issue is that this is not bound to the correct object. I would suggest you look into Function.bind() because that creates a function with this pointing to the right thing.

different ways to execute javascript code?

I see
First
$(function() {
...
});
Second
(function() {
})();
Third
function() {
}
$(document).ready(function(){
});
Maybe there are more, what are the differences?
Your notation is mainly jQuery (atleast the ones with $)
This is shorthand for a DOM ready function, equivalent to the bottom one
This is a self executing function with the parameter specified in the trailing ()
This is a DOM ready function $(document).ready(function() {}); atleast, the function above it is simply a function.
so these indeed are a few different ways to execute javascript code, some of them are library dependent (using jQuery) others are done specifically because of differences in scope.
the first block:
$(function() {
...
});
is utilizing the js library jQuery that uses the namespace '$' what you are doing here is calling the jQuery '$' function passing in the first parameter of another anonymous function... this is a shorthand way to call $(document).ready(function(){});... both of those statements wait for the DOM to complete loading (via the onload event) before interpreting the javascript inside
the second block:
(function() {
})();
is a procedure called an (IIFE) Immediately-Invoked Function Expression... which in essense is defining an anonymous function and calling it immediately.
the third block:
function() {
}
$(document).ready(function(){
});
represents two things... the first function declared actually should have been named something like function myFunction(){...} and thus could be called later myFunction(parameters);
and finally $(document).ready(function(){}); is the javascript library jQuery's way of saying grab the 'document' element of the dom, and attach an event listen to it looking for the onload event, when that event is triggered execution the function passed as a parameter...

How to pass 'this' to an event using backbone?

I have an event that binds a function to a click. The click calls another function in the same view. Unfortunately, the scope is not the correct scope. When I try to do this.otherFunction(), the function that is assigned to the click is not in the same scope as this.otherFunction(). Is there a way to pass in the scope of otherFunction()?
initialize: function() {
this.render();
if (joinedGoalList.get(this.model.id) != null) {
this.renderLeaveGoal();
} else {
this.renderJoinGoal();
}
},
events: {
"keypress #goal-update": "createOnEnter",
"click #join-goal": "joinGoal",
"click #leave-goal": "leaveGoal",
},
joinGoal: function() {
matches = joinedGoalList.where({id: this.model.get("id")});
if (matches.length == 0) {
joinedGoalList.create({goal_id: this.model.get("id")}, {wait: true, success: function() {
var self = this;
self.renderLeaveGoal();
}, error: function() {
console.log("error");
}});
}
},
renderLeaveGoal: function() {
console.log("render leave goal");
var template = _.template($("#leave-goal-template").html());
console.log(template);
$("#toggle-goal-join").html(template());
},
These are all under the same view.
Edit:
Hmm, now the problem is that I get this error:
Uncaught TypeError: Object [object DOMWindow] has no method 'renderLeaveGoal'. Does this seem that I saved the wrong scope?
Standard technique is to do something like
var self = this;
Then you can do
self.otherFunction();
In place of
this.otherFunction();
deltanovember's answer is correct, but he didn't explain why it's correct, and I feel that's important:
Scope is messy in Javascript. I've found the easiest way to keep track of it is to think about when something will execute. If a block of code executes right away, it's probably running in the same scope as "this". If a function is going to be called later, it's probably running in a completely different scope, with its own concept of "this".
In your example, the anonymous function you're providing as that success callback is going to run later, and it won't be scoped to the same "this" as the code that's running when said callback is defined. This is why you're getting an error: renderLeaveGoal was defined in the scope where the callback was defined, but not the scope where the callback will be executed.
Now, to make this more confusing, variables defined when a callback is defined will be available within that callback's scope. This is why deltanovember's answer works. By disguising "this" in a variable when the success callback is defined, the callback can still access it when it runs later, despite the completely different scope.
I hope that makes sense. Comment if it doesn't, and I'll try again :)
You can also use Underscore's bindAll function like so:
initialize: function() {
_.bindAll(this);
}
Behind the scenes, Underscore will replace all function calls in the object with proxied versions that set "this" to be the same "this" as your original object. Of course, if one of your methods has its own anonymous callback functions inside it, then you'll need to do the whole "self = this" dance; bindAll only fixes the context of your "outer" methods on the object.
I've gotten into the habit of using _.bindAll as the first line in each of my View's initialize() methods.
The function is attached to the view, so you need to call it off of the View object.
success: this.renderLeaveGoal
In this case, you don't need the anonymous function because the view functions are automatically bound to the view's context.

jQuery Function Implementation and Function Call?

What is the difference of calling function like:
testCall: function() and function testCall() in jQuery ?
Update:
Questions: Does usage of one over the another have some performance issues related to it OR it really does not matter which one you are using ?
Update 2
Also other thing that I noticed that whenn I am defining function using testCall: function() and I call it using this.testCall() it works fine and am able to call it in any other function.
But when I am using function testCall() and I try to call it using testCall() in another function than I am getting errors and am not able to call it. Is this possible or there could be some other reason for the errors ?
In this example:
testCall: function()
testCall is now a function available on the object you're in, like this: object.testCall() It can access other functions, properties, etc inside this object if it needs to.
In this version:
function testCall()
testCall is just a globally available method, not scoped to the object or plugin, whatever you're dealing with, you can call it from anywhere, like this: testCall()
This is really a question about Javascript syntax (and semantics), not jQuery.
Both of those constructions define functions. This:
var x = {
// ...
name: function() { /* ... */ },
// ...
};
defines a function (an anonymous function) and assigns it as the value of the property called "name" in the object being assigned to the variable "x".
This:
function name() {
/* ... */
}
defines a function with the name "name". The effect is similar to:
var name = function() { /* ... */ };
but definitely different. However, for most purposes it's safe to think about them as being almost the same. The effect is that "name" is bound to the function in the lexically-enclosing scope. If you do that definition outside of any other function, then "name" becomes a property of the "window" object, and the function is therefore globally available. If that declaration is inside another function, then "name" is only available inside that function.
Usually you see the first form when you're doing something like setting up callbacks for some jQuery facility, like a UI plugin or $.ajax. You're giving jQuery a function that it should call upon something happening — an AJAX call finishing, or a use action like a mouse click, or completion of some sort of animation.
edit oh, and finally here's another note. If you define a function the second way, well then you can refer to that function by name and use it in an object definition (like the first example):
function globalFunction() {
function localFunction() { /* ... */ };
jQuery.something({
x: 100, y: 100,
callback: localFunction,
// ...
});
}
Many more such things are possible - functions are values in Javascript and can be tossed around as easily as numbers and strings.
The first (testCall: function()) is object literal notation for defining a function and assigning it to a property on an object (not shown). The function itself is anonymous; the property it is bound to has a name, but the function does not.
The second (function testCall()) is a named function.
Named functions have several advantages over anonymous ones, and so though you see the first format quite a lot, I would recommend using it sparingly if at all. Named functions can be reported usefully by your tools (debuggers and the like), whereas anonymous functions just show up as ? or (anonymous). More here.
For that reason, rather than this:
function doSomeNiftyAjaxyThing(foo) {
$.ajax({
url: "blah",
success: function() {
// Do something involving the successful result and `foo`
foo.bar();
}
});
}
I would typically do this instead:
function doSomeNiftyAjaxyThing(foo) {
$.ajax({
url: "blah",
success: niftySuccess
});
function niftySuccess() {
// Do something involving the successful result and `foo`
foo.bar();
}
}
Not only does this keep my code a bit cleaner (er, to my mind), but it means that if something goes wrong inside niftySuccess, I've given the function a name my tools can report to me. Note that other than the fact that the function has a name, they're identical – both functions are closures over the foo argument and anything else inside doSomeNiftyAjaxyThing.
You might be tempted to give the function a name inline, like so:
function doSomeNiftyAjaxyThing(foo) {
$.ajax({
url: "blah",
success: function niftySuccess() { // <== change here, PROBLEMATIC
// Do something involving the successful result and `foo`
foo.bar();
}
});
}
There you're declaring a function with a name as an expression, and assigning the result of the expression to a property. Arguably you should be able to do that, but there are a series of implementation...anomalies in the various Javascript engines out there that prevent your being able to do that. (More in the article linked above, and in this article.)

Inline functions and other method's scope

How do I make the myFunction visibile for the in-line function in .ready() event?
$(document).ready(function() {
...stuffs...
myFunction(par1, par2, anotherFucntion_callback);
}
);
function anotherFunction_callback(data) {
..stuffs..
}
I didn't quite catch your question. Do you mean that you want to pass "myFunction_callback(data)" as the last argument in your:
myFunction(par1, par2, anotherFunction_callback);
, including that "data" parameter?
In that case the solution is pretty standard, write this before that one:
var temp = function() { anotherFunction_callback(data) };
an alternative syntax is:
function temp() { myFunction_callback(data) };
// even though this looks just like a free function,
// you still define it inside the ready(function())
// that's why I call it "alternative". They are equivalent.
In general, if you want to pass a function with 1 or more arguments to another function, you use that format. Here, we basically create a new no-argument function that calls another. The new function has access to the "data" variable. It's called "closure", you may want to read more on that.
Of course, if the callback require no argument, you can just use the original function name.
I hope this helps.
ps: You can even inline the function declaration, making it anonymous, like so:
myFunction(par1, par2, function() { myFunction_callback(data) });
Notice that the
$(document).ready(function() {});
looks pretty much just like that.
You use the actual name of the function, i.e. myFunction_callback instead of myFunction or anotherFucntion_callback.

Categories

Resources