Javascript function declaration tutorial
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> // 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