Are named functions underrated in JavaScript? - 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.

Related

Immediately Invoked Function Expression: Where to put the parenthesis?

I've seen IIFE's written:
(function() {
console.log("do cool stuff");
})();
as well as:
(function() {
console.log("do more cool stuff");
}());
They seem to work the same in any context I've used them, though in cases I've been told one way is right and the other is wrong, vice versa. Does anyone have any solid reason or logic as to it being written one order over the other? Is there some cases where there could be potentially more going on after the function body closes but before the invoking parenthesis come into play, or after but before that final closing parenthesis? I've mostly used these in an Angular module closures and can't seem to find anything on any real reason to go one way or the other, wondering if anyone had different experience.
Short answer: It doesn't matter, as long as you put them there.
Long answer: It doesn't matter except in the case of arrow functions, because for JavaScript the only important thing is that they are there. The reason for this is that the language spec defines that a statement must only start with the function keyword if you declare a named function. Hence, it is against the spec to define an IIFE like that:
function () {}();
The workaround for this is to wrap the entire thing in parentheses, so that the statement does not start with the function keyword anymore. You achieve this by using
(function () {})();
as well as by using:
(function () {}());
Which one you choose is completely arbitrary and hence up to you.
I (personally) put the parentheses around the function, not around the call, i.e. like this one:
(function () {})();
Reason: I want to use the smallest portion of code to be wrapped in something that is only needed for technical reasons, and this is the function definition, not the call. Apart from that the spec says that you can not define a function in that way, it is not about calling the function. Hence, I think it's more clear if you wrap the definition, not the call.
edit
However, in the case of the arrow function in es6, the invocation must be outside of the wrapper. It being inside the wrapper causes an unexpected token error on the opening parenthesis of the invocation. Not totally clear on the mechanics of why this is so.

javascript: reason for declaring and immedieatly calling inline function

So I had an interview where I was asking the purpose of declaring and calling a function immideately, and i couldn't answer it, i.e:
(function(){
// code
})();
What's the reason for doing this?
Object-Oriented JavaScript - Second Edition: One good application of immediate (self-invoking) anonymous functions
is when you want to have some work done without creating extra global
variables. A drawback, of course, is that you cannot execute the same
function twice. This makes immediate functions best suited for one-off
or initialization tasks.
The syntax may look a little scary at first, but all you do is simply
place a function expression inside parentheses followed by another set
of parentheses. The second set says "execute now" and is also the
place to put any arguments that your anonymous function might accept:
(function() {
})();
or
(function() {
}());
are the same:

Grammar of Self Invoking Anonymous Functions

From what I have read from other topics about the issuse SIAFs or Self Invoking Anonymous Functions are simply there to serve as a container, and it limits the scope of variables (from what I have learnt). Now, the question is, why can I do this:
$("ul>li").click((function(){
}));
But not add another SIAF after it? Like so:
$("ul>li").click((function(){
}));
(function(){
});
It is weird to me, as this, just the SIAF on its own gives me no errors in the IDE:
$("ul>li").click((function(){
}));
(function(){
});
This:
(function() { .. });
is a no-op expression, and in particular it does not involve a function call. A function object is instantiated but it's not used in any way.
This:
(function() { ... })();
does do something, because the trailing () causes the function to be invoked. (It doesn't invoke itself.)
In JavaScript, a reference to a function is just a value, and a function is just an object (well, a special object). When a reference to a function is followed by a parenthesized list of values, then that's a function call. It doesn't matter where the reference to the function comes from. (Where it comes from can affect the semantics of the function call, but not the basic fact of the function call itself.)
edit — the terminology "self-invoking function expression" has gained some currency. I won't wade into a dispute, but in my opinion it's less accurate than the alternative "immediately-invoked function expression" because really a function can't invoke itself externally. It can include a call to itself, but that's a different thing entirely. However I understand the spirit of the term and I think it's harmless.

HTML5 drag & drop events in Javascript

I followed a little tutorial on Drag & Drop in HTML with Javascript, found here:
http://www.html5rocks.com/tutorials/dnd/basics/
The problem is, I'm working with an in-house style restriction. Meaning all documents have to be written to standards that everyone here uses.
For Javascript, one of them is to always write functions in the object-notation.
I.e.
var myFunction = function() {}
instead of
function myFunction() {}
In this tutorial, the events for the HTML5 drag & drop are added via the addEventHandler() function. This requires you use the normal notation, because if you use the object-notation, the addEventHandler() function trips over it for some reason.
I tried re-writing everything to be like this, without addEventHandler:
myElement.dragstart = function(e) {}
But non of it worked. Using the normal notation with addEventHandler however, everything works like a charm.
I just wanna make sure: am I overlooking something or should this work? Part of me suspects this is just not supported properly yet and you need to use addEventHandler. Is this the case?
Setting the dragstart property vs using addEventHandler('dragstart', ...) is not just a matter of notation. You can and should stick with addEventHandler. There should be no problem, however, using this "style:"
var myFunction = function() {}
myElement.addEventListener('dragstart', myFunction, ...);
Edit
Okay, so this doesn't directly answer the question, but I feel it does need to be addressed in this context.
Writing
var myFunction = function() {}
instead of
function myFunction() {}
is not any sort of "object notation." The first is a function expression, since it's part of an AssignmentExpression. The second is a function declaration. What's the difference? kangax explains it really well:
First of all, function declarations are parsed and evaluated before any other expressions are. Even if declaration is positioned last in a source, it will be evaluated foremost any other expressions contained in a scope.
...
Another important trait of function declarations is that declaring them conditionally is non-standardized and varies across different environments. You should never rely on functions being declared conditionally and use function expressions instead.
Do the people who set the JavaScript code standards in-house really understand the subtle differences?
Point number 1: that's a stupid rule. There are two ways of naming a function for a good reason, and ignoring that to specify one style is fairly dim, IMO.
Your problem is, I think, that your function hasn't been defined by the time you get to addEventHandler. This is because of something called "hoisting". In this process, functions named with the function myFunction() {} syntax are "hoisted" to the top of the function. So if you invoke them anywhere in the function, the function will work. For instance, this will work:
el.addEventListener('click', foo);
function foo() {}
Functions named in your organisation's style, however, are not hoisted. The variable declaration is, but the value is not set until that line of code is reached. So this will not work:
el.addEventListener('click', foo);
var foo = function() {};
The easiest way to get around this would be to move all your function definitions to the top of the scope, unless there is a good reason to define them later. So this will work:
var foo = function() {};
el.addEventListener('click', foo);

Javascript Function Syntax

In my feeble attempt to learn JavaScript, I bought a book which teaches you how to do things in JavaScript, but forgets to mention WHY.
Coming from PHP I am familiar with the typical function syntax:
function name() {return;}
which from what I understand works the same in JS.
Then I decide I want to attempt to use the YUI 3 framework for a small project to continue learning and come across this...YUI Global Object
YUI().use('node', function(Y) {
Y.Node.get('#demo');
});
As far as I understand this is using the 'use' function of the YUI() object, passing 'node' to the 'use' function....but then what...why is it declaring a function within another function call?
Could someone please explain the syntax being used here?
Also a good reference that explains JavaScript general syntax's similar to php.net would also be beneficial.
Thanks for your help.
Its an anonymous function. Its considered a callback.
In PHP 4 and early versions of PHP 5 you might see something like this:
PHP
function callback($var){
...
}
array_filter( $array, "callback" );
In later versions of PHP 5 you can define them as anonymous functions inline.
So, in JavaScript, the old version would look like this:
JavaScript
function use_callback(Y){
Y.Node.get('#demo');
}
YUI().use('node', use_callback);
But by defining an inline anonymous function, you can save the extra clutter and defined function:
YUI().use('node', function(Y) {
Y.Node.get('#demo');
});
Both those functions are equivalent.
In javascript, functions can be passed around as variables. So, here's some other ways that the YUI code could have been written
//original
YUI().use('node', function(Y) {
Y.Node.get('#demo');
});
//more traditional "global function"
function useNode(Y) {
Y.Node.get('#demo');
}
YUI().use('node', useNode);
//local callback function
var myUseNode = function(Y) {
Y.Node.get('#demo');
}
YUI().use('node', myUseNode);
edit As for the second half of your question, you could write what I know about PHP on a postage stamp, so I can't help you there, sorry :-)
This is constructing an anonymous function, and then passing the function itself in as an argument to use. The use method will then call your anonymous function with a value, which in your function will be called Y, which contains the modules that you asked for in the previous arguments to use.
This is essentially equivalent to the following, which passes myFunction in as a callback to YUI().use, except that the anonymous function doesn't have a name:
function myFunction(Y) {
Y.Node.get('#demo');
}
YUI().use('node', myFunction);
This pattern is used because JavaScript doesn't have any kind of explicit notion of namespaces or modules. They can be emulated, however, by using the scope of a function to act as a sort of namespace. In this case, YUI().use will construct an object that has all of the functionality that you request, and pass that object in to the function you provide, so you can use that Y object to call methods that you have imported.
For a good online reference on JavaScript syntax and methods, I like to use the Mozilla Developer Center documentation. In particular, they have good references on JavaScript and the DOM. As it is part of the Mozilla project, they focus on the methods and syntax supported by Gecko (the rendering engine of Firefox), but they usually include compatibility notes to mention what is portable and what is specific to Gecko.
For your question, I would recommend reading the MDC documentation on functions and function scope. Sadly, the MDC doesn't usually come up on top on a Google search; instead, you get W3Schools, which tends to be lower quality and have more ads. I've found it useful to always prefix my searches for anything about JavaScript or the DOM with "mdc" in order to get the MDC documentation; so, for instance, to find that link, I searched for mdc function, and found what I needed.
In JavaScript, functions are objects. In that case, they are passing in an object as the second parameter value (and defining it inline).
YUI().use('node', function(Y) {
Y.Node.get('#demo');
});
is the same as this:
var xxx = function(Y) {
Y.Node.get('#demo');
};
YUI().use('node', xxx);
It is an anonymous function (akin to lambda function) declaration.
YUI().use('node', function(Y) {
Y.Node.get('#demo');
})
In Javascript, functions are 1st class citizens - they are objects like any other; hence, they can be passed as parameter.
What is being shown is what is known as an anonymous function that is being passed as an argument to a function. I don't think PHP has first-class functions like this, so I have no idea how to explain the syntax in terms of that (I also don't do much with PHP, so..)
Here is my example code:
function something_random(a) {
alert("the type of a is ... " + typeof(a));
if (typeof(a) === 'function') {
a();
}
}
Now with this function in mind, you can plug this into Firebug or something similar and run the following code:
something_random(function () {
alert("This is a test.");
});
Something interesting will happen here - you will get two alerts. One should say "the type of a is... function" and the other should say "this is a test." This is because in JavaScript - as well as some other languages - functions are treated just like objects (well, they technically are objects.)
You can throw around functions all day if you like - they are just like numbers, arrays, and so on.
Something interesting can also happen. You can also pass arguments into anonymous functions, which is something that jQuery does quite a bit (except it uses call, but we won't go there.) This is where you get the special things like where you put function(d) {} in a code.
Hope this helps.

Categories

Resources