Report abuse

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
Functions
=========

One of the best features of JavaScript is its implementation of functions. Whereas other languages present you with different function types for different purposes, JavaScript only has one function type that covers all function use-cases--from subroutines to lambdas to class methods.

But while JavaScript's function type may look simple enough on the outside, the intricacies that hides underneath a basic function declaration is amazingly complex. And while topics like function forms, scope, context, and function execution may seem too complicated for practical consideration, learning about these things that usually go unnoticed improves your knowledge of the language and provides you with an arsenal to solve even the most complex of problems.


JavaScript Functions
====================

From here on, we'll define a ***function*** as a block of code that performs a certain action and returns a value. It can receive *arguments*, which are values passed to the function and can be used to compute the resulting return value. A function can also be run multiple times by *invoking* it.

    // a basic function with two arguments:
    function sum(one, two){
        return one + two;
    };
    
    // invoking the function and passing arguments:
    var result = sum(1, 42);
    console.log(result); // 43
    
    // invoking the function again, but with different arguments:
    result = sum(5, 20);
    console.log(result); // 25
    

JavaScript is a language with *first-class functions*: functions can be stored in variables, passed as arguments to other functions and even used as return values for other functions. This is possible because functions, like almost everything else in JavaScript, are objects. The language also allows for creating new functions as well as transforming defined functions at runtime, which as we'll see later on, enables MooTools to add improvements to native JavaScript.


One Function, Multiple Forms
============================

While there is only one function type in JavaScript, there are multiple *function forms*, which are the different ways to create a function. The base syntax for all these forms is called the ***function literal*** and it looks like this:

    function Identifier(NamedArguments, ...){
        FunctionBody
    }

First you have the `function` keyword, followed by a space then an optional *identifier* used to reference your function; then a pair of parentheses that encloses an optional comma-separate list of *named arguments*, which are variables that will be available inside of your function; and finally, you have the option *function body* where you write the bulk of your function's code.

> You'll notice that there are a lot of things that are optional in the base syntax, and you'll see why in a moment. The following is a legal (albeit useless) JavaScript function:

    function(){}

Because functions are objects, they also have methods and properties. We'll talk more about methods and properties of objects in Chapter 3, but for now, let's remember that a function object has basic two properties: 
    
    - `name` is a string that corresponds to the function's identifier, and
    - `length` is an integer that refers to the number of NamedArguments in the function (or 0 if there are no named arguments).

Function Declaration
--------------------

From the base syntax, we can create the first function form, called a *function declaration*. The following code defines a new function called `sum`:

    // a function named `sum`
    function sum(a, b){
        return a + b;
    };
    
    console.log(typeof sum);    // 'function'
    console.log(sum.name);      // 'sum'
    console.log(sum.length);    // 2

    console.log(sum(20, 5));    // 25

In a function declaration, the identifier is required, because it'll be used to reference your function. The `name` property of the function will be `sum`, equivalent to the function identifier and the `length` property is 2, because we have two named arguments

A function declaration is the most simple of all function forms, and most developers use this form for their code.

In our example, the outer function is available in the global scope but the inner function is available only within the outer function. This is because function declaration scopes the second function as a local object inside the first one.

Because JavaScript is *lexically scoped*, functions are scoped based on where they are defined rather than on their syntax or where they are executed. This is important because the language allows us to define functions inside other functions, and scoping rules might get confusing:

    // outer function, global scope
    function outer(){
        
        // inner function, local scope
        function inner(){
            // ...
        };
        
    };
    
    // check the outer function
    console.log(typeof outer);          // 'function'
    
    // run outer to create the new functions
    outer();
    
    // check the inner function
    console.log(typeof inner);  // 'undefined'

We'll learn more about the details of scoping in a while, so let's first take a look at other function forms.

Function Expression
-------------------

The next function forms take advantage of the fact that functions can be stored in variables. This form is called *function expression* because rather than explicitly defining a function, you express a function as a value of a variable.

Here's the same `sum` function we declared above, but using a function expression:

    var sum = function(a, b){
        return a + b;
    };
    
    console.log(typeof sum);    // 'function'
    console.log(sum.name);      // '' / 'anonymous'
    console.log(sum.length);    // 2

    console.log(sum(20, 5));    // 25

In the example above, we create a function literal which becomes the value of our variable `sum`. We can then use this variable to invoke our function, as seen in the last line where we use the function to add two numbers.

While the `length` property of the function is the same with its function declaration counterpart, you'll notice that the `name` property is different. In some JavaScript engines, it's value will be a blank string (`''`), while in others it'll be `'anonymous'`. This happens because we didn't specify an identifier for the function literal. In JavaScript, a function without an explicit identifier is called an *anonymous function*.

The scoping rules for function expressions are a bit different from function declarations because they depend on variable scoping. Remember than in JavaScript, the `var` keyword defines a variable to be scoped locally, and omitting the keyword will create a global variable instead. 

    // outer function, global scope
    var outer = function(){
        
        // inner function, local scope
        var localInner = function(){
            // ...
        };
        
        // inner function, global scope
        globalInner = function(){
            // ...
        };
        
    };
    
    // check the outer function
    console.log(typeof outer);          // 'function'
    
    // run outer to create the new functions
    outer();
    
    // check the new functions
    console.log(typeof localInner);     // 'undefined'
    console.log(typeof globalInner);    // 'undefined'

The function `outer` is defined to be global scope, because while we use the `var` keyword, it's on the top-level of the application. Inside the function are two other functions, `localInner` and `globalInner`. The `localInner` function is stored in a variable that's local to the inside of the `outer` function and cannot be accessed in the global scope. However, `globalInner` is stored in a variable that's defined without the `var` keyword, making the variable and the function it contains both globals.

Named Function Expression
-------------------------

Although function expressions are usually written using anonymous functions, you can also specify an explicit identifier for your function. This is a variation of the function expression, which I term as a *named function expression*.

    var sum = function sum(a, b){
        return a + b;
    };

    console.log(typeof sum);    // 'function'
    console.log(sum.name);      // 'sum'
    console.log(sum.length);    // 2

    console.log(sum(20, 5));    // 25

The example above is the same with a function expression that uses an anonymous function, but we specify an identifier for the function literal. Unlike the previous example, the `name` property of the function above is `'sum'`, which consistent with the identifier we specified, rather than 'anonymous' or an empty string.

The main purpose of allowing an explicit identifier for function expressions is to create a way for functions to reference themselves from the inside. It might look weird that such a declaration is allowed in JavaScript and the purpose might not be so clear at first, so let's look at some examples.

    var myFn = function(){
        // reference the function
        console.log(typeof myFn);
    };
    
    myFn(); // 'function'

In the example above, the function `myFn` could easily reference itself via the variable holding it because the variable that contains the function is available inside the function scope. However, consider this next example:

    // global scope
    var createFn = function(){
        
        // result function
        return function(){
            console.log(typeof myFn);
        }
        
    };
    
    // different scope
    (function(){
        
        // put the result function of `createFn`
        // into a local variable
        var myFn = createFn();
        
        // check if reference is available
        myFn(); // 'undefined'
        
    })();

Some parts of the example will be discussed later, but we'll focus on what's happening first. On our global scope, we create a new function called `createFn`, which returns a new logging function like our example before. Next, we create a new local scope and define a variable `myFn` and assign the return value of `createFn`.

The code is similar to our previous example, but here, we use the resulting function value of another function instead of directly assigning the function literal to the variable. Also, the variable `myFn` is on a different localized scope, which is not accessible to our resulting function value. Thus, it'll log `'undefined'` rather than `'function'` in this case, because the scoping doesn't allow the function to reference itself via the variable holding it.

By adding an explicit identifier to our result function, we'll be able to reference the function itself even if we don't have access to the variable holding it:

    // global scope
    var createFn = function(){
        
        // result function, with identifier
        return function myFn(){
            console.log(typeof myFn);
        }
        
    };
    
    // a different scope
    (function(){
        
        // put the result function of `createFn`
        // into a local variable
        var myFn = createFn();
        
        // check if reference is available
        myFn(); // 'function'
        
    })();

Adding an explicit identifier is like creating a new variable that's available from inside the function that can be used to reference the function itself, making it possible for the function to call itself from the inside (for recursive operations) or perform actions on itself.

A named function declaration has the same scoping rules as a function declaration with an anonymous function: the scope of the variable determines whether the function will be local or global. However, the additional identifier has a different scoping rule: it's only available from inside the function:

    // a function with different
    // identifiers
    var myFn = function fnID(){
        console.log(typeof fnID);
    };
    
    // the variable
    console.log(typeof myFn);   // 'function'
    
    // the identifier
    console.log(typeof fnID);   // 'undefined'
    
    myFn(); // 'function'
    
The example above shows that while the variable `myFn` could be used to reference the function, the identifier `fnID` isn't accessible from the outside. However, accessing this identifier variable from the inside of the function itself works.


Single-Execution Function
-------------------------

We touched the subject of anonymous functions in passing before and while they are useful for function expressions, they have much broader usage. One of these is a technique where an anonymous function is used to create a function that's executed immediately without storing references to it. I'll call this form is called a *single-execution function*.

    // create a function and invoke it immediately
    (function(){
        
        var msg = 'Hello World';
        console.log(msg); // 'Hello World'
        
    })();

In the example above, we create a function literal and wrap it inside a pair of parentheses. We then use the *function invocation operator* or `()` in order to execute the function immediately. The function isn't stored in a variable, nor is any reference to it created. It's a "run-once" function: create it, do whatever it does and then move on.

In order to understand how a single-execution function works, we need to remember that functions are objects and objects are values. Because JavaScript values can be used immediately without having to store them in variables, you can create anonymous functions which you immediately execute just by appending a function invocation operator.

However, notice that we wrap our function inside a pair of parentheses in the previous example, instead of doing it like this:

    // this is considered as a syntax error
    
    function(){
        
        var msg = 'Hello World';
        console.log('msg'); // 'Hello World'
        
    }();
    
A JavaScript engine will throw a syntax error when it encounters these lines because it interprets the code as a function declaration. It sees a function literal but no identifier, and it throws an error because a function declaration requires an identifier to follow the `function` keyword.

We need to wrap the function in parentheses in order to tell the JavaScript engine that it is not a function declaration, but rather, that we are creating a function and we use its value immediately. Because we have no identifier that we can use to reference the function, we need to wrap it in parentheses in order to create a direct reference to the function and enable us to directly call it. This wrapping in parentheses is only needed when we have no direct reference to the function like with single-execution functions.

Note: The invocation operator can be included within the parentheses or outside it, like so: `(function(){... }())`. Putting the operator outside is more common, though, and it's considered as the proper MooTools-style.

A single-execution function is useful for a lot of cases and the most important of these is to keep variables and identifiers inside a localized, protected scope. Consider the following example:

    // top level scope
    var a = 1;
    
    // localize scope with a single
    // execution function
    (function(){
        
        // local scope
        var a = 2;
        
    })();
    
    console.log(a); // 1

Here, our first variable `a` is declared in the top scope, making it available globally. We then create a single execution function and redeclare `a` inside, changing its value to `2`. But because this is a localized variable, the original top-level `a` variable does not change.

This technique is popular, especially with library developers, because localizing variables into a separate scope avoids identifier clashing. If you include two scripts that define the same identifier within your application, chances of one of them overwriting the value of the other is high--unless one of them localizes their scope via a single-execution function.

Another way of using a single-execution function is when you want to perform a task using a function and use its return value using a throwaway function:

    // Store a single-execution function's
    // return value to a variable
    var name = (function(name){
        
        return ['Hello', name].join(' ');
        
    })('Mark');
    
    console.log(name); // 'Hello Mark'

Don't get confused with the code above: that is not a function expression. What's happening is that we create a single-execution function that's immediately invoked, and returns the value that we want to store in our variable.

Another feature of single-execution functions is their ability to have an identifier, just like with a function declaration:
    
    
    (function myFn(){
        
        console.log(typeof myFn); // 'function'
        
    })();
    
    console.log(typeof myFn); // 'undefined'

While it may seem like we're doing a function declaration, this is actually a single-execution function. Even though we specify an identifier for the function, it does not create a variable in the current scope like a function declaration does. This enables you to reference the function from inside itself without creating a new variable inside the current scope.

Like any other function, single-execution functions can receive arguments passed via the invocation operator. Combine this with an identifier available from inside the function and the ability to store the return value of a single-execution function and you can create quick recursive functions for your code:

    var number = 12;
    
    var numberFactorial = (function factorial(number){
        return (number == 0) ? 1 : number * factorial(number - 1);
    })(number);
    
    console.log(numberFactorial); // 479001600

Function Object
---------------

The last function form, the *function object*, is different from all the rest because it does not use a function literal. The basic syntax of this form is as follows:

    new Function('NamedArguments, ..., 'FunctionBody');

Here, we use the `Function` constructor to create a new function by passing strings arguments. The first arguments define the named arguments for the function, and the last argument defines the function body.

Note: While we call this form a *function object*, remember that all functions are objects. We simply use this term to differentiate between a function created via a literal and via an *object constructor*, which will be discussed in the next chapter.

Here's our `sum` function using this form:

    var sum = new Function('a', 'b', 'return a + b;');
    
    console.log(typeof sum);    // 'function'
    console.log(sum.name);      // '' or 'anonymous'
    console.log(sum.length);    // 2

    console.log(sum(20, 5));    // 25

You'll notice that the code similar to using an anonymous function literal. Like an anonymous function, a function object has either a blank string or `'anonymous'` for its `name` property value. In the first line, we create a new function using the `Function` constructor, passing in the arguments `'a'`, `'b'` and `'return a + b;'`. The first two strings will become the named arguments of the function, and the final string will become the function body. Using this form is like using `eval`: the last string argument is turned into valid JavaScript code and used as the body for the function. 

Note: You don't need to pass the named arguments as separate string. The Function constructor also allows for a single string containing comma-separated name values, like so: `new Function('a,b', 'return a + b');`

While this form has its uses, as we'll see in a latter part of this book where it'll be used for a templating engine, a Function object has a disadvantage over a function literal because the function's scope is limited to the global scope:

    // global variable
    var x = 1;
    
    // localized scope
    (function(){
        
        // local x variable
        var x = 5;
        
        // a function object
        var myFn = new Function('console.log(x);');
        myFn(); // 1, not 5.
        
    })();

Even though we have a local variable `x` in our separate scope, the function object will not be able to reference this because it's evaluated in the global scope. This has huge implications when it comes to closures and limits the usefulness of function objects.