Sorry for the rather beginner question. What's the differences of function usage between
$(document).keypress(function() {
//some code
});
and
var somethingElse = function() {
//some code
};
I know the latter is to create a function similar to Java's
public void somethingElse() {
//some code
}
but I always assume the former as anonymous function that act inside a method. Can someone shed me some light regarding this? Thanks.
The first one is a jQuery shortcut to create an event listener.
It's equivalent to:
document.addEventListener('keypress', function() {
// some code
});
More info: http://www.w3schools.com/jsref/met_document_addeventlistener.asp
Now, about named or anonymous functions, what's the difference between
var doSomething = function() {
// some code
};
and this?
function doSomething() {
// some code
}
There's no difference for the developer. Of course there's a difference on memory, but in javascript developers don't have to take care of it.
Actually for the case of an event handler or other techniques that use callback functions, you can pass an anonymous function or a previously declared one, it's exactly the same:
$(document).keypress(doSomething);
or
$(document).keypress(function() {
// some code
});
creates an anon function and passes it to the handler
creates an anonymous function and a variable that references it.
creates a named function - that is hoisted
the hoisted function becomes available to you at any line within your function scope, while the non-hoisted function will be undefined until the line where it is declared runs.
there is no difference between #2 and #3 (other than the hoisting) - some people think that the first one creates an object and the 2nd one is some magical thing, or a global function, but nope - they are both function objects within your scope.
The former is a callback, meaning some instructions that will be executed ONLY as soon as the keypress event in your example is triggered.
Thus, a function's name is not required.
Function expressions, the latter, is mostly used when adding an object's property acting as a method like:
var myObject = {};
myObject.sayHello = function() {
alert("Hello");
}
Related
Can someone clarify this point for me?
Two of my favourite features in JavaScript are closures and the fact that functions are first class objects.
If I want to take advantage of closure in, say, a callback function, then the function must always be an inner function. For example:
doNested();
function doNested() {
var message='Hello';
window.setTimeout(inner, 3000);
function inner() {
alert(message);
}
}
There is no way I can pass a parameter to an outer callback function. For example:
doSeparated();
function doSeparated() {
var message='Goodbye';
window.setTimeout(outer,3000);
}
function outer() {
alert(message);
}
This doesn’t work, of course.
The question is, is there any way to pass inner variables to an external function like this, short of adding them to a parameter list?
Thanks
If I want to take advantage of closure in, say, a callback function, then the function must always be an inner function.
That's correct. Every function in JavaScript only has access those variables which are either defined in its own scope or defined in a parent scope1. Therefore, your first example works while your second example doesn't.
The question is, is there any way to pass inner variables to an external function like this, short of adding them to a parameter list?
No, there's no way to do that. Well, technically you could add your inner variable to an object and then bind that object to the external function after which you can access the inner variable from the this context of the external function, but that is no better than passing the variable to the function directly.
doSeparated();
function doSeparated() {
var message = "Goodbye";
setTimeout(outer.bind({
message: message
}), 3000);
}
function outer() {
alert(this.message);
}
Since you are using setTimeout, you can pass extra arguments to setTimeout which will be given to the callback function. This gets rid of the nasty bind:
doSeparated();
function doSeparated() {
var message = "Goodbye";
setTimeout(outer, 3000, message);
}
function outer(message) {
alert(message);
}
Note that both bind and extra arguments of setTimeout don't work in older versions of IE. In that case, you can use currying instead (which in my humble opinion is the best solution aside from your original nested solution):
doSeparated();
function doSeparated() {
var message = "Goodbye";
setTimeout(outer(message), 3000);
}
function outer(message) {
return function () {
alert(message);
};
}
Other than these, there's no other good solution that I can think of. The best solution is your original nested solution.
1 A function doesn't have access to any variable defined in a child scope or else you would be able to access every variable from the global scope.
I am trying to sharpen my JavaScript skills and I am aware that there are four basic ways to invoke a function - which alter the way this is defined. The two I am interested in are the basic two:
Invocation as a function
Invocation as a method
Which is fine. The first, this will refer to the window object:
function doSomething() {
console.log(this);
}
doSomething(); // window is logged
And the second this will refer to the object it is being executed from within:
var t = {
doSomething: function () {
console.log(this);
}
};
t.doSomething(); // t is logged
Which is all fine. However, is it correct to say, that in these two invoking methods, this is always going to return the object the method is contained within (if that makes sense)?
In the first example, doSomething() is, in reality, defined within the window object - so is a property of the window object, even if we do not define it (or reference it).
Therefore, can it not be said that, in reality, invocation as a function is invocation as a method? Or not?
Imagine defining your function, not in the scope of the global object like you did, but in the scope of another function:
function outer() {
var inner = function(){console.log(this)};
inner();
};
outer();
What do you think the this will be bound to ? What will be printed ?
You might believe it will be the outer function object but its turns out that it will always be the global object.
It is just as if you had written:
function outer() {
var inner = function(){console.log(this)};
inner.call(window);
};
outer();
This is a quite hazardous and far from intuitive JS "feature".
So, to get back to your first example, what you are doing is basically this:
doSomething = function () {
console.log(this);
}
doSomething().call(window);
And, like Yoshi pointed out, if you were using the ES5's strict mode, you would end up doing something like that instead, which is, in my opinion, far less dangerous:
doSomething().call(undefined);
It also gives you a strong hint about the fact that you should never use this in a function ;)
I've just come across this little snippet of JavaScript code online:
exampleSocket.onopen = function(event) { // rest of code here;}
And I'm rather confused about the function(event) part, as there are no comments for me to analyze. (Who needs comments when you're designing bi-directional duplex connections? Haha ).
What exactly is function(event)? I always thought you had to define a function name with the function in javaScript. Is this an example of bad code? Additionally, the (argument-parameter-whatever) 'event' isn't even defined anywhere else in the code. Just bam. There it is. Is it necessary to define that, or is (event) a special predefined value? Lastly, if you were to replace (event) with some other value like (e), would the code still work?
Thanks
What you've got there is a function expression, not a function statement.
In a function statement, the name is mandatory. In a function expression it is optional. A function expression with a name is called a named function expression. A function expression without is called an anonymous function
There are a number of subtle differences between all these different methods of declaring a function which are covered in this question; var functionName = function() {} vs function functionName() {}
What you're doing here is setting the onopen property of exampleSocket to a function (expression). Note that you are not running that function at all; you are simply declaring it, and saving a reference to it in exampleSocket.onopen.
This means that someone can execute that function when they want to by calling;
exampleSocket.open();
They can pass a parameter to the function, which you can use inside the function using the event variable (and to answer your question; event is not a special word. You can call it anything).
exampleSocket.onopen = function (event) {
console.log(event); // will log "hello"
};
exampleSocket.open("hello");
The fact the variable event isn't used anywhere will likely mean the developer has named the argument to say "hey, look, you can use this if you want to", but hasn't in his actual implementation.
You don't have to declare the variable yourself. It is declared already by being named in the argument list, and it will be initialized to a value when someone passes an argument when they call the function.
Note that we could define this event handler using a function statement;
function foo(event) {
console.log(event);
}
exampleSocket.open = foo;
... or via a named function expression:
exampleSocket.open = function foo(event) {
console.log(event);
};
To confuse things (don't worry about this; it's a quirk of JavaScript) the name of a named function expression is only available inside the function itself;
exampleSocket.open = function foo(event) {
console.log(event);
console.log(typeof foo); // you'll get "function"
};
console.log(typeof foo); // you'll get "undefined"
... but in a function statement, you'll be able to access the name both inside and out.
I hope this helps... it's a bit of a "brain dump" of information :).
This is an anonymous function. A function is a value, and you can declare and store functions like this. More information on that syntax in this question.
Reading the code (I don't think it needs any more comments than it already has), you are writing a handler function which is called when the socket opens. The socket open event will be passed to the function in the variable event.
Why event? Because the API, whatever it is, expects to pass in an argument that represents the 'open' event.
It's a simple and common JS event-binding function.
It attach an anonymous function to the "open" event of "exampleSocket".
When such event is fired the declared function is called.
Each event may have some parameters, which contain additional info about the event itself.
You can name that parameter the way you want ("event","e" or "anythingElse") and then you can refer to it in the anonymous function body.
You are basically assigning a function value to exampleSocket.onopen, which can then be called elsewhere. Imagine something like this:
var obj = {};
obj.onsomething = function(a, b, c, d) {
alert(a+b+c+d);
};
obj.onsomething(1, 2, 3, 4);
In this case, I gave obj.onsomething a function that takes 4 parameters (should be numbers) and alerts the sum. Then I can just call obj.onsomething with 4 parameters.
So the function that you assign to exampleSocket.onopen will get called when it is appropriate (for example, when the socket is open).
Hope that helps.
I have a function like this:
function run(arg) {
if (!window.alreadyRun) init();
window.alreadyRun = true;
/* more code */
}
You get the idea, I'm trying to figure out if it's the first time a function is called.
Is there a better way to do this? Without using globals? Something like this:
function run(arg) {
var ranAlready;
if (!ranAlready) init();
ranAlready = true;
/* more code */
}
This will return a function, with a variable called runCount which will hold the number of times it was called.
var yourFunction = function() {
var runCount = 0;
return function() {
console.log(runCount);
runCount++;
}
}
var a = yourFunction();
a(); // runCount: 0
a(); // runCount: 1
a(); // runCount: 2
a(); // runCount: 3
See it on jsFiddle.
If you just want to run an init type function, you could place the code above returning the inner function. It will be called once before returning the inner function, and its scope will retain to its outer function.
The power of closures.
var f = (function(run) {
return function() {
if (!run) init(),run=true;
// do code
};
}(false));
You can even use if (!run) init() && run = true and get init to return false if you want it to be called again on the next function call.
We have a self executing function which creates a local run variable and set's it to false by passing it in as an argument. We then have a single line which checks if it's false if so it does init(), run=true which is running the init function and assigning it to true in a single expression.
Basically anywhere were your using global scope to make the variable static to the function you can instead use a closure as a scope level between local function scope & global scope.
If you need a variable that is static to a function & read only you can use the little known const keyword.
I think closures are completely overkill for this, and only complicates the code.
What you're describing is known as a static variable in Object Oriented languages, and it can be mimicked quite easily in JS by attaching properties directly to the function. This is possible because functions are first-class objects in JS:
function run(arg) {
if (!run.ranAlready) { // run.ranAlready is undefined at first, so falsy
run.ranAlready = true;
init();
}
/* more code */
}
This is far simpler than nested functions, and you can continue to use run() in exactly the same way.
Another advantage is that, for unit testing, you can still access the ranAlready property from outside the function to check that your code is working correctly:
assert(run.runAlready == false);
run();
assert(run.runAlready === true);
Granted, this can't be used for anonymous functions, such as in event handlers, but isn't it much cleaner to give that anonymous function a name instead of using nested functions and an extra function invocation?
Here's just another way to do it. You can have the function modify itself. In the case below, myfunction gets changed to a new one. This may not be exactly what you're looking for but I think it's useful to at least post this so you can see alternative ways to do things (and also: self modifying code can just be cool at times).
var myfunction = function() {
alert("This is the first time I'm executed");
myfunction = function() {
alert('Subsequent times');
}
}
myfunction(); // displays the alert 'This is the first time...'
myfunction(); // displays the alert 'Subsequent times'
myfunction();
Example: http://jsfiddle.net/jonathon/wntmB/
Using instance methods as callbacks for event handlers changes the scope of this from "My instance" to "Whatever just called the callback". So my code looks like this
function MyObject() {
this.doSomething = function() {
...
}
var self = this
$('#foobar').bind('click', function(){
self.doSomethng()
// this.doSomething() would not work here
})
}
It works, but is that the best way to do it? It looks strange to me.
This question is not specific to jQuery, but specific to JavaScript in general. The core problem is how to "channel" a variable in embedded functions. This is the example:
var abc = 1; // we want to use this variable in embedded functions
function xyz(){
console.log(abc); // it is available here!
function qwe(){
console.log(abc); // it is available here too!
}
...
};
This technique relies on using a closure. But it doesn't work with this because this is a pseudo variable that may change from scope to scope dynamically:
// we want to use "this" variable in embedded functions
function xyz(){
// "this" is different here!
console.log(this); // not what we wanted!
function qwe(){
// "this" is different here too!
console.log(this); // not what we wanted!
}
...
};
What can we do? Assign it to some variable and use it through the alias:
var abc = this; // we want to use this variable in embedded functions
function xyz(){
// "this" is different here! --- but we don't care!
console.log(abc); // now it is the right object!
function qwe(){
// "this" is different here too! --- but we don't care!
console.log(abc); // it is the right object here too!
}
...
};
this is not unique in this respect: arguments is the other pseudo variable that should be treated the same way — by aliasing.
Yeah, this appears to be a common standard. Some coders use self, others use me. It's used as a reference back to the "real" object as opposed to the event.
It's something that took me a little while to really get, it does look odd at first.
I usually do this right at the top of my object (excuse my demo code - it's more conceptual than anything else and isn't a lesson on excellent coding technique):
function MyObject(){
var me = this;
//Events
Click = onClick; //Allows user to override onClick event with their own
//Event Handlers
onClick = function(args){
me.MyProperty = args; //Reference me, referencing this refers to onClick
...
//Do other stuff
}
}
If you are doing ES2015 or doing type script and ES5 then you can use arrow functions in your code and you don't face that error and this refers to your desired scope in your instance.
this.name = 'test'
myObject.doSomething(data => {
console.log(this.name) // this should print out 'test'
});
As an explanation: In ES2015 arrow functions capture this from their defining scope. Normal function definitions don't do that.
var functionX = function() {
var self = this;
var functionY = function(y) {
// If we call "this" in here, we get a reference to functionY,
// but if we call "self" (defined earlier), we get a reference to function X.
}
}
edit: in spite of, nested functions within an object takes on the global window object rather than the surrounding object.
One solution to this is to bind all your callback to your object with javascript's bind method.
You can do this with a named method,
function MyNamedMethod() {
// You can now call methods on "this" here
}
doCallBack(MyNamedMethod.bind(this));
Or with an anonymous callback
doCallBack(function () {
// You can now call methods on "this" here
}.bind(this));
Doing these instead of resorting to var self = this shows you understand how the binding of this behaves in javascript and doesn't rely on a closure reference.
Also, the fat arrow operator in ES6 basically is the same a calling .bind(this) on an anonymous function:
doCallback( () => {
// You can reference "this" here now
});
I haven't used jQuery, but in a library like Prototype you can bind functions to a specific scope. So with that in mind your code would look like this:
$('#foobar').ready('click', this.doSomething.bind(this));
The bind method returns a new function that calls the original method with the scope you have specified.
Just adding to this that in ES6 because of arrow functions you shouldn't need to do this because they capture the this value.
I think it actually depends on what are you going to do inside your doSomething function. If you are going to access MyObject properties using this keyword then you have to use that. But I think that the following code fragment will also work if you are not doing any special things using object(MyObject) properties.
function doSomething(){
.........
}
$("#foobar").ready('click', function(){
});