Skip to content

Instantly share code, notes, and snippets.

@vaz
Created October 16, 2012 21:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vaz/3902294 to your computer and use it in GitHub Desktop.
Save vaz/3902294 to your computer and use it in GitHub Desktop.
Javascript function declaration tutorial
> // There are two different ways to define functions in javascript.
> // Functions can be named, or anonymous.
> // The named function syntax looks more like a C- or Java-style "statement":
> function f(){ }
undefined
> // Notice it evaluates to "undefined". I'll come back to this in a sec.
> // The named function syntax binds the function to a local variable with the given name.
> f
[Function: f]
> // It also actually names the function object:
> f.name
'f'
> // ----
> // The other syntax is the anonymous syntax.
> // This syntax treats function declaration as an expression with a return value,
> // rather than a C-style statement:
> var g = function(){ }
undefined
> g
[Function]
> // this allows you to define functions on the fly, similar to Ruby blocks.
> function threetimes(block){
... for(var i=0; i<3; i++){ block(); }
... }
undefined
> // using an anonymous inline function:
> threetimes( function(){ console.log('hi'); } );
hi
hi
hi
undefined
> // You can see how you could do something like ruby's each { ... } in this way.
> // (several javascript libraries give you functional goodies like each, map, filter, ...)
> // however! there's a bit more to this story.
> // it can be kind of annoying sometimes to have a function with no name.
> // remember g, from above?
> g.name === ''
true
> // :(
> // even though it's assigned to variable 'g', the actual function object is nameless.
> // this is kinda crappy for stack traces:
> threetimes( function(){ imbroken; });
ReferenceError: imbroken is not defined
at repl:1:25
at threetimes (repl:2:25)
...
> // this is a trivial example that would not be hard to trace, but...
> // I could store an anonymous function in a variable and only call it later,
> // in response to some event... leading to a flow of logic that is less clear.
> // in that case, the namelessness might be a nuisance.
> // ----
> // Let's look again at the ways we can declare functions.
> // the named, statement-style way:
> function f(){ }
undefined
> f
[Function: f]
> f.name
'f'
> // the unnamed, expression-style way:
> var g = function(){ }
undefined
> g
[Function]
> g.name
''
> // Can't we do both? Inline functions with names?
> var m = function n(){ }
undefined
> // we can! but...
> n
ReferenceError: n is not defined
at repl:1:2
...
> // it doesn't bind a variable for the "name", in this form.
> // however...
> m
[Function: n]
> m.name
'n'
> // this is still good.
> // Hey wait! I thought "function f(){ }" evaluated to undefined?!
> // how can we now be assigning it to a variable?
> // It seems the javascript interpreter has a quirk... an exceptional case.
> // It treats a bare function declaration differently
> // if you use it as an expression, than if you write it like a "statement".
> // (remember though, like Ruby, everything is really an expression in JS)
> (function x(){ }) // parentheses force it to be treated as an "expression"
[Function: x]
> // however it doesn't bind the name:
> x
ReferenceError: x is not defined
at repl:1:2
...
> // what it comes down to is that "function x(){ }" is roughly equivalent to...
> var x = function(){ }; x.name = 'x'; undefined
undefined
> // except...
> x
[Function]
> x.name
''
> x.name = 'x'
'x'
> x.name
''
> // it seems name is a read-only property.
> // this means the only time a function can be named is when it's declared!
> // ---
> // ok. back to blocks/callbacks...
> // now we can provide a name to our inline function, and have nicer stack traces:
> threetimes( function broken_function(){ imbroken; } );
ReferenceError: imbroken is not defined
at broken_function (repl:1:41)
at threetimes (repl:2:25)
at repl:1:1
...
> // you pretty much don't see anyone using named, inline functions,
> // but you should, because it's a cool feature.
> // :)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment