After adding a callback function to $.Callbacks(), I want to remove it again:
var callbacks = $.Callbacks(),
foo = function() { console.log('Hello world') };
callbacks.add(foo);
callbacks.fire(); // logs 'Hello world'
callbacks.remove(foo);
callbacks.fire(); // nothing to trigger, removed perfectly
So, that works, but now I want to add an anonymous function, like so:
callbacks.add(function(){ console.log('Hello anonymous world') });
callbacks.fire(); // logs 'Hello anonymous world'
Looks fine, but I can't remove the function anymore:
callbacks.remove(function(){ console.log('Hello anonymous world') });
callbacks.remove();
callbacks.fire(); // still logs 'Hello anonymous world'
Is there a way to overcome this?
Per OP Request:
Functions are identified by pointer. You have no pointer to your anonymous function, so you have nothing to pass to remove() to tell it which function to remove. Simply passing a duplicate function doesn't do it, because the duplicate has a different pointer. You need to stick with assigning the function to a variable, then passing that variable to remove().
Reference: http://api.jquery.com/category/callbacks-object/
You could remove it from within the function itself (like at the last line of the function) using arguments.callee (a reference to itself) although arguments.callee is not valid in 'strict mode'.
Related
Let's assume that I define a self-executing function like the following :
({
function1: function(){//...}
function2: function(){//...}
})
How can I call function2 from inside function1 ?
(I tried calling it just like : function2(); and this.function2(); , none worked, both returned error : function2() or this.function2() is not a function)
Actually this is part of the Aura framework, so maybe it is specific to this framework.
There are several things wrong here. First, this is not a self-executing function. This is an object with two functions defined inside it and wrapped in parentheses, which make it invalid. Something like this would be a valid JavaScript object:
object1 = {
function1: function(){
console.log('function1 called!'); // logs the text 'function1 called!' to the console
},
function2: function(){
console.log(this); // logs the details of `object1`
this.function1();
}
};
object1.function2();
Equivalent functionality using an anonymous function would look something like this:
(function (){
console.log('anonymous function called!');
})();
Note the lack of curly brackets surrounding the anonymous function. Unlike the functions in the object, the anonymous function isn't a member of any object. Also note the last set of parentheses at the end, those are what triggers the execution of the anonymous function that has just been defined.
JavaScript functions: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions
I'm a Backbone, Javascript, jQuery noob and trying to figure things out. In my Backbone view, I have this method:
setError: function (selection, text) {
console.log("set error");
this.$el.find(selection).html(text);
this.$el.find(selection).show();
},
I want to call this method, from another method that populates the error field, and also append other messages in the div. So I try calling setError like this:
populateErrors: function (sampleErrors) {
console.log("populateErrors");
_.each(sampleErrors, function (sample) {
// Set the error
this.setError('#sample-error', 'test');
$('#sample-validation-form').append('<p>testing</p>');
}, this);
}
What I don't understand is how to call setError. So If I call it outside of the _.each statement, I can do this.setError. That makes sense to me since I'm calling setError with this Backbone object. At least that's how I'm interpreting it. Please let me know if that is incorrect.
But then in the _.each statement, I thought since I am binding the statement with this as the last parameter, I thought I would not need this in front of setError. But when I try that, I get setError is undefined. So then I try this.setError as seen above, but I do not get my 'test' output like I do when I call this.setError outside of the _.each loop. Can someone please explain to me how this function context works in this example. I'm thoroughly confused! thanks in advance!
When you pass an object foo as the third argument, you are saying: within the anonymous function, this should be foo.
populateErrors: function (sampleErrors) {
// `this` is the Backbone view here
this.setError('#sample-error', 'test');
_.each(sampleErrors, function (sample) {
// since you passed the view (this) to `each`
// `this` is the Backbone view here also
this.setError('#sample-error', 'test');
}, this);
}
The third parameter to _.each is the context. The context of the javascript function is the reference to what "this" will be in the function. By passing "this", you get to keep your current context.
For Example:
populateErrors: function (sampleErrors) {
var x = {
blah: "x context"
};
this.blah = "orig context";
console.log("populateErrors");
_.each(sampleErrors, function (sample) {
// Here, your current context is the same context as
// when you called populate Errors
// this.blah === "orig context";
}, this);
_.each(sampleErrors, function (sample) {
// Here, you've defined a different context.
// this.blah === "x context";
}, x);
}
The only time you can avoid using "this." in front of your expression is when you use the "with" key word. See https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/with
Consider this:
window.onload = function () {
myObj.init();
};
var myObj = {
init: function () {
console.log("init: Let's call the callMe method...");
//callMe is not defined...
callMe();
//Works fine!
this.callMe();
},
callMe: function () {
console.log('callMe');
}
};
Since the init function gets called this way (myObj.init), I expect this to be myObj in the init function. And if that is the case, why the callMe function fails? How am I supposed to call the callMe function without using the this context in the init body? (Actually, it's too annoying to call the object methods using this over and over again through the functions. So what's the point of having a single object?)
I would like to know how can I fix this so that the callMe method gets called using the first invocation in the code above?
this is never implicit in JavaScript as it is in some other languages. Although there are ways to do it, like this using the with statement:
init: function () {
console.log("init: Let's call the callMe method...");
// Make `this` implicit (SEE BELOW, not recommended)
with (this) {
// Works
callMe();
}
},
...it's generally a bad idea. Douglas Crockford probably wrote one of the better descriptions of why it's a bad idea, which you can find here. Basically, using with makes it nearly impossible to tell what the code's going to do (and slows the code down, if you do anything else in that with statement that doesn't come from the this object).
This isn't the only way that JavaScript's this is not the same as it is in some other languages. In JavaScript, this is defined entirely by how a function is called, not where the function is defined. When you do this.callMe() (or the equivalent this["callMe"](), or of course foo.callMe(), etc.), two things happen: The function reference is retrieved from the property, and the function is called in a special way to set this to be the object that property came from. If you don't call a function through a property that way, the call doesn't set any particular this value and you get the default (which is the global object; window on browsers). It's the act of making the call that sets what this is. I've explored this in depth in a couple of articles on my blog, here and here.
This (no pun) can be made even clearer if you look at JavaScript's call and apply functions, which are available on all function objects. If I do this:
callMe.call({});
...it'll call the callMe function with a blank object ({}) as this.
So basically, just get used to typing this. :-) It's still useful to have properties and methods associated with an object, even without the syntactic convenience (and confusion!) of an implicit this.
You can also use the module pattern, which captures all private variables inside a closure, so you are free to use them without this, as they're in the same scope. You then pick and choose which methods/variables you want to make public:
var myObj = (function () {
var init = function () {
callMe(); // This now works
};
var callMe = function () {
...
};
// Now choose your public methods (they can even be renamed):
return {
init: init, // Same name
callMyName: callMe // Different name
};
}) ();
Now:
myObj.init(); // Works
myObj.callMyName(); // Works
myObj.callMe(); // Error
HTML
<button id='hello'>Click Me!</button>
JavaScript (wrong)
$('#hello').click(alert('Hello, World!'));
JavaScript (correct)
$('#hello').click(function() {
alert('Hello, World!');
}
I'm wondering why the first JS code triggers on the event load instead of click. Can anyone tell me why function() { [code] } is needed for the script to work properly?
In this example, I used jQuery events, but this is not specific to it, for example, I need to use it with setTimeout, too.
The click function expects another function as a parameter.
In the first case you would be passing the result of calling alert('hello world');, which is null.
The second is just a shorthand for:
$('#hello').click(callback);
function callback(){
alert('hello world');
}
Because .click() is a handler. The first argument is a function to assign. But if you actually pass the function with arguments then it will call the function (in this case alert) and then pass it's return value.
Writing $('#hello).click( function() { } )` is basically a short hand for writing:
var myfunction = function() {
// code
};
$('#hello').click( myfunction );
As you can see in the long hand way, it's passed as a reference to the function instead of the function's return value.
Your first example says "evaluate
alert('Hello, World!')
right now, and pass the result as an argument to click. "
The second says "Define a function which will do the alert when I call it, and pass that whole function as an argument to click.
The function() { ... } syntax is how you declare an anonymous function in Javascript. jQuery uses lots of these to specify that some action will be performed later, like when an event occurs. You can think of it as delaying the execution of your function until necessary. Without this syntax, whatever code you place there is evaluated immediately, which is not what you want for an event handler.
You might think, "why isn't JavaScript smart enough to know the difference?" Consider this:
function returnCallback(linkId, data) {
return function(e) {
alert('Clicked on ' + linkId + '. Here is some data: ' + data);
// Maybe do some stuff with e, the event parameter
}
}
$('#some-link').click(returnCallback('some-link', 'some-data'));
$('#other-link').click(returnCallback('other-link', 'different-data'));
This is a contrived example, but it illustrates the power of anonymous functions and closures. This works since returnCallback returns a function.
In the first instance, "JavaScript wrong", you're actually calling alert('Hello, World!') at the point that the script is loaded. Now, the reason you pass the .click function a function is because it can call it at any point. Essentially, you're packing code together to be run (or not run at all) at any point when you put it in a function.
$('#hello').click(alert('Hello, World!')); is attempting to run alert('...') and pass its return value to the .click() function which will not work as expected.
This is because JavaScript evaluates everything and during this process your alert is invoked. You can use anonymous function or you can also use your own custom function as implemented below:
<script language="javascript" type="text/javascript">
$("#mybutton").click(clickFired);
function clickFired() {
alert('click fired');
}
</script>
The parameter required for the .click() function is a Function. Therefore $("#hello").click(function { [code] }); is required. Because there's nothing to return by alert().
The click function here assigns a value to the event handler.
With the first ("wrong") code you're assigning a value of alert('Hello, World!') which is itself a function call, so it's going to be immediately evaluated and hence appear at load.
With the second ("correct") code you're now assigning a new anonymous function which is not executed itself, just instantiated at load. Hence this will work as expected later.
somefunction(alert('hello! world'));
this would mean you want to pass to somefunction the return value of alert("hello! world").
jquery click expects a callback that it should fire upon click on the element. so you put it in a function which does not execute unless someone (here jquery) calls it explicitly.
I have a javascript function (function1) that checks some global variables (can the user connect, is the service available, etc) before calling another (legacy) function (function2) that actually pops a window and connects the user to our service. I want to prevent function2 from being called anywhere but from function1. Is this possible?
As a cheap solution, I figured I could emit a variable from function1 and check for it in function2 before executing. Is there another way? Is there a way to find out the calling element/method in a javascript function?
Read here: Crockford's method. Declare the function inside the first function.
You should check this:
How do you find out the caller function in JavaScript?
and this:
https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function/caller
Why not just remove function2, move its entire content into function 1 ?
Then you can just replace the old function 1 with something that signals the error.
you can move function2 inside of function1 so that's it's "private" to function1. check out the "module pattern".
var function1 = function() {
var function2 = function() { alert('hi'); };
function2();
};
function1(); // alerts "hi";
function2(); // error function2 is undefined