Function declaration vs expression from a performance point of view? - javascript

There's many javascript articles on the web comparing function declarations function foo (){} to function expressions var foo = function () {}. They usually mention things like hoisting, behaviour within conditionals, etc... But I don't recall any of them talking about performance. Is there any difference? Particularily in ECMA5's strict-mode (if that changes anything).
By performance I of course mean execution performance (including lookup, scope traversal, etc..) not declaration performance, although that would be a nice-to-know aswell.

Function declarations are faster in cases where there's a potential for the function expression to be evaluated multiple times. For example, in code that is called in a loop a hoisted function is only evaluated once, but an expression would be evaluated each time. Besides that, there's no meaningful difference.
Whenever you have a question about a JavaScript performance issue, I recommend checking out JSPerf. Also, Google to see if someone already made one for your question, and in this case they have:
http://jsperf.com/function-declaration-vs-function-expression/15

I executed the same tests from JSPerf in Chrome canary 45 and Firefox 37, sadly the results are opposite:
function myfunc() {
alert("yo");
}
myfunc();
Chrome: fastest, FF: much slower
var myfunc = function() {
alert("yo");
}
myfunc();
FF: fastest, Crome: much slower
So, the answer is: it depends from the browser/JS engine.

Related

JavaScript function declaration hoisting from within loops [duplicate]

W.r.t Hoisting of fxn definitions.
if (true) {
function foo() {
alert(1)
}
} else {
function foo() {
alert(2)
}
}
foo()
Chrome, some 2-3 months ago - would print 2. Now, it's printing 1. Did I miss something or, did console stop hoisting on fxn's!
DEMO -- prints 1. I'm not sure where to find demo of the older browser version. Probably older v8 engine's node installation?.
Current chrome version - 49
The code you have is invalid in strict mode. Functions don't get hoisted out of blocks (or at least they shouldn't), function declarations inside blocks were completely illegal until ES6. You should write
"use strict";
var foo;
if (true) {
foo = function() {
alert(1)
};
} else {
foo = function() {
alert(2)
};
}
foo()
to get the desired behaviour with reproducible and expected results.
Did I miss something or, did console stop hoisting on fxn's!
Looks like V8 was updated to align with the ES6 spec. It does "hoist" them to the function/top scope, but only when the declaration is actually encountered (in your case, conditionally).
You should avoid using conditionally created functions.
For example, assume the following code:
if (false){
function foo(){
console.log(1)
}
}
foo()
Firefox will not hoist the function and this will result in ReferenceError: foo is not defined. Chrome, however, hoists the function nonetheless and prints 1. So obviously you have deal with different browser behaviour. Therefore, do not do things like that at all (or use function expressions if you really want to).
Also see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function
Functions can be conditionally declared, that is, a function statement can be nested within an if statement. Most browsers other than Mozilla will treat such conditional declarations as an unconditional declaration and create the function whether the condition is true or not, see this article for an overview. Therefore they should not be used, for conditional creation use function expressions.
Especially look at the linked article which somewhat explains the issue you are seeing. So Chrome seems to have changed something in that regard. But again, do not use conditionally created functions.
And note that, as FREEZE commented, you should use 'use strict'; which would not allow such code but throws an exception instead.

Javascript closures performance

I have being working for a while in javascript and usually do something like this just to cache the value of properties of functions that are declared inside a deep structure or "namespace"
//global scope
(function ($, lib) {
//function scope 1
var format = lib.format, // instead of calling lib.format all the time just call format
touch = lib.pointer.touch, //instead of calling lib.pointer.touch each time just touch
$doc = $(document),
log = logger.log; //not console log...
$doc.on('app:ready', function () {
//function scope 2
$doc.on('some:event', function (e) {
//function scope 3
//use the cached variables
log(format('{0} was triggered on the $doc object', e.type);
});
$doc.on(touch, function (e) {
//function scope 3
log(format('this should be {1} and is... {0} ', e.type, touch);
});
});
}(jQuery, lib));
I was doing that because:
as lazy as I am, writing touch seem more appealing that writing lib.pointer.touch, even when powerful IDEs with fancy autocompletion could help on this, touch is shorter.
a minimizer could convert that single private variable to a single letter variable, so it also made sense for me (I know, I know, never optimize too soon, but this seems to be safe I guess)
All the code written that way seems to perform decently on mobile devices and desktop browsers, so It seems to be a safe practice (In "the practice", pun intended). But I since this relies in closures, and inner functions have to create a closure to save the context it was declared I was wondering...
if a function does not uses variables from the outside context (free variables)... is the closure context still saved? (or if i a tree falls in the wood and nobody is there to hear it, does it still make the crash sound? hehe) I'm aware that this could vary between javascript engines, because ECMA mention nothing about if it is required to save the context or not when variables from the outside are not accessed.
if the above expression is true... will this block of code be more efficient?
//global scope
(function ($, lib) {
//function scope 1
var format = lib.format,
touch = lib.pointer.touch,
$doc = $(document),
log = console.log;
$doc.on('app:ready', function () {
(function ($doc, touch, lib, format) {
// since all the variables are provided as arguments in this function
// there is no need to save them to the [[scope]] of this function
// because they are local to this self invoking function now
$doc.on('some:event', function (e) {
//function scope 3
//use the cached variables
log(format('{0} was triggered on the $doc object', e.type);
});
$doc.on(touch, function (e) {
//function scope 3
log(format('this should be {1} and is... {0} ', e.type, touch);
});
}($doc, touch, lib, format));
});
}(jQuery, lib));
Is it more efficient because it passes those variables to self immediate invoking function? will the cost of creating that new function any impact in the code, (negative or positive)?
How I can properly measure the memory consumption of my javascript library in a reliable way? I have 100x little javascript modules all inside immediate self invoking functions mostly to avoid variables from leaking to the global context. So They all are wrapped in modules very similar to the block of code mentioned above.
will it have a better effect to cache the variables closer, even when that will mean I will have to repeat the declarations of the variables closer to where they're going to be used?
I have the feeling that looking for a variable not in the current local context, the engine will first look into the parent scope and iterate over all the variables at that level... the more variables per level, worse would probably be the performance looking for a variable.
try to find an undefined variable from the internal closures will be the most expensive, because by definition the variable will be first search on the parent scope until the global scope, and not finding it will force the engine to finally reach the global scope. Is that true? are engines optimizing this kind of lookups?
In the end... I know that I will not want to implement my code as the second example mostly because It will make the code harder to read and I'm kinda confortable with the minimized size of the final output using the first approach. My question is motivated by the curiosity and to try to understand a bit better this really nice feature of javascript.
Accordingly to this test...
http://jsperf.com/closures-js
It seems the second approach is faster. But is only evident when iterating an insane number of times... Right now my code does not do that number of iterations... but probably is consuming more memory because of my way of coding...
update: it has being pointed to me that this question is too large. I'm sorry will try to break in small parts. This question was motivated mostly by curiosity as I said, performance seems negligible even in mobile devices. Thank you for all your feedback.
I think it is premature optimization. You already know performance is not a problem in most cases. Even in tight loops, performance does not degrade that bad. Let the JavaScript engine optimize this on its own as Chrome has started doing, by removing unneeded variables from closures.
One important thing is, don't make your code harder to read with unnecessary optimization. Your example takes quite a bit more code, hampering development. In some cases, we are forced to make the code harder to read because we know a particular piece of the app is more memory/performance intensive, but only at that point should we do that.
If you add a breakpoint to the following code (in Chrome), you'll see that the world variable has been optimized out of the closure, look at the 'Closure' node under the Scope Variables http://jsfiddle.net/4J6JP/1/
.
(function(){
var hello = "hello", world="world";
setTimeout(function(){
debugger;
console.log(hello);
});
})()
Note that if you add an eval in that inner function, then all bets are off and the closure can't be optimized.

Why variable hoisting after return works on some browsers, and some not?

alert(myVar1);
return false;
var myVar1;
Above code throws error in IE, FF and Opera stating that return statement has to come in the function. But it works (shows undefined) in Safari and Chrome.
The above code has been written in global scope. Outside all the functions.
Any reason?
In JavaScript variables are moved to the top of script and then run. So when you run it will do
var myVar1;
alert(myVar1);
return false;
This is because JavaScript doesn't really have a true sense of lexical scoping. This is why it's considered best practice to have all your variables declared at the top of the area they will be used to prevent hoisting causing a problem. JSLint will moan about this.
This is a good article that explains it: http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
The return is invalid. If you want to do a true hoisting example (taken from the link above) do
var foo = 1;
function bar() {
if (!foo) {
var foo = 10;
}
alert(foo);
}
bar();
This will alert 10
Below is my understanding and I have read it somewhere but can't find all the sources that I read so am open to correction.
This Alerts thanks to the differences in the JavaScript JIT. TraceMonkey(http://ejohn.org/blog/tracemonkey/) I believe will take the JavaScript and do a quick static analysis and then do JIT and then try to run it. If that fails then obviously nothing works.
V8 doesn't do the static analysis and moves to the JIT then runs so something. It's more akin to Python. If you run the script in the Developer console (ctrl+shift+j in Windows) in Chrome it will throw an error but also run to give you the alert.
Sometimes hoisting is explained in a way which may give wrong impression, i.e. the variables and functions are hoisted by JavaScript engine as if they were physically moved on top, which is not actually right, as demonstrated by the code below:
console.log(a);
var a = 'Hello World!';
What we see on console is undefined, not 'Hello World', so we got the behavior of the following code
var a;
console.log(a);
a = 'Hello World!';
not the behavior of
var a = 'Hello World!';
console.log(a);
which you may get the impression from the variables and functions declaration being moved to top statement.
But JavaScript is not actually moving your code anywhere. You need to understand execution context in JavaScript. It has two phases creation phase and execution phase. In creation phase memory space is created for these variables and functions, and people seem to confuse this step with hoisting. JavaScript is actually not moving your code anywhere, what happens is JavaScript has created memory space for all your code i.e. variables and functions, functions can be placed fully in memory but in case of variables the assignments are processed in execution phase of the execution context. So when you do var a = 'Hello World!', JavaScript engine knows the value of a when it starts executing it in execution phase of execution context, so it puts a placeholder undefined, and all variables are initially set to undefined in JavaScript. So it is not good to rely on hoisting and see undefined. So it is always good to declare variables and functions on top of your code.
Section 12.9 (page 75) of ECMA-262 edition 3 states:
An ECMAScript program is considered syntactically incorrect if it contains a return statement that is not within a FunctionBody.
That is, a return outside of a function is a syntax error. If a syntax error occurs, no code is run. Think about your example as if you had written:
alert(myVar1);
return false;
syntax error))))))))))))))))));
In addition, section 16 (page 157) states:
An implementation may treat any instance of the following kinds of runtime errors as a syntax error and therefore
report it early:
Improper uses of return, break, and continue.
Firefox's engine et. al. (i.e. those JavaScript implementations which allow return in the global scope) may be conforming, assuming the following clause (in the same section) allows for implementation definition of return in the global scope:
An implementation shall report all errors as specified, except for the following:
An implementation may provide additional types, values, objects, properties, and functions beyond those described in this specification. This may cause constructs (such as looking up a variable in the global scope) to have implementation-defined behaviour instead of throwing an error (such as ReferenceError).
This code makes little sense:
The var myVar1 will never be ran.
The return false; will not return a thing since you're not in a function
Opera, IE and FF are right to throw an error because this code is really not valid since you're not able to return unless you are in a function.
If it works in Safari and Chrome it must be because the javascript engine they use is ready to handle buggy code. My guess would be that they see the "return" and drop or replace it with some kind of break.
More information about functions: http://www.w3schools.com/js/js_functions.asp
It is JavaScript Hoisting thing, Simply in other words, we are trying print the value of the variable , which is not holding any value
Javascript will render the above code as:-
var myVar1
alert (myVar1)
return false
To clarify more i refered the link javascript hoisting: http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html

most efficient javascript method declaration

While writing javascript, one can define a method in 3 different ways.
1] A function in global namespace
function doSomething();
2] A function that is member of a function
function Clazz() {}
Clazz.doSomething = function(){};
3] A function that is memeber of the instance of function
function Clazz() {}
Clazz.prototype.doSomething = function(){};
Depending upon the code organization, one can choose one of the above methods over others.
But purely from performance standpoint which is the most efficient one? (especially between 1 and 2)
Will your answer be different if doSomething has arguments?
From a pure performance POV, 1 should be the fastest. The reason being that it would require less work to setup the scope chain & execution context. Also if you access any global variables from within the function, the resolution will be fastest with 1, again simply because of the depth of scope chain.
As a general rule further up (near to the global) an object is in the scope, the faster it is. for the same reason accessing property a.b will be faster than accessing a.b.c
The performance gain might not be too much in case of a simple function call, however it can mount up if say you call the function n a loop.
None of those declarations do the same thing and aren't interchangeable, what kind of comparison do you expect? It's like asking if it's faster to instantiate 10 variables or an array with 10 items: one is fastest, but the result is not the same.
You cannot compare performance between the function declarations,
For example add(a,b) functions declared in all the 3 places give the same performance. performance matters by how you write your code, not by where you declare your functions...
you are missing the most optimized one:
var x = function(){}
When javascript sees the definition:
function x(){}
It then converts it into the former form. If you do it that way in the first place there is a negligable speed up. But for the sake of answering your question, this is the most optimal.

Are named functions underrated in JavaScript?

Taking the jQuery framework for example, if you run code like this:
$(document).ready(function init() { foo.bar(); });
The stack trace you get in Firebug will look like this:
init()
anonymous()
anonymous([function(), init(), function(), 4 more...], function(), Object name=args)
anonymous()
anonymous()
As you can see, it's not very readable, because you have to click on each function to find out what it is. The anonymous functions would also show up as (?)() in the profiler, and they can lead to the "cannot access optimized closure" bug. It seems to me that these are good reasons to avoid them. Then there's the fact that ECMAScript 5 will deprecate arguments.callee in its strict mode, which means it won't be possible to reference anonymous functions with it, making them a little less future-proof.
On the other hand, using named functions can lead to repetition, e.g.:
var Foo = {
bar: function bar() {}
}
function Foo() {}
Foo.prototype.bar = function bar() {}
Am I correct in thinking that this repetition is justified in light of the debugging convenience named functions provide, and that the prevalence of anonymous functions in good frameworks like jQuery is an oversight?
I agree there are certain downsides to using anonymous methods in JavaScript/EMCAScript. However, don't overlook how they should be used. For simple one liners that you want to pass to another function, they are often excellent.
I found the answer to my question in this very informative article. Firstly, it turns out that I was right about named functions being more desirable, but the solution is not as simple as adding identifiers to all anonymous functions. The main reason for this is JScript implementing function expressions in a very broken way.
Secondly, there is a distinction between function statements and expressions. An anonymous function is just a function expression with the identifier omitted, and adding an identifier (naming it) wouldn't make it a statement (except in JScript, which is why it's broken). This means that all of the other answers were off mark.
But for me anonymous functions are more readable in the source code, because I am sure they are only used there.
Anonymous functions are very convenient. A better fix to this problem, instead of naming the functions, would be if firebug told you on which line in which file the anonymous function was created.
init()
anonymous() // application.js, line 54
anonymous() // foo.js, line 2
And the stack trace is the only place where anonymous functions are a problem imo.

Categories

Resources