|
| 1 | +Many new features were introduced to JavaScript with the release of newer specifications like ECMAScript 2015, |
| 2 | +also known as [ECMAScript 6 or ES6](https://developer.mozilla.org/en/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla). |
| 3 | +While the Guides [assume you have a working knowledge of JavaScript](/#toc_assumptions), |
| 4 | +not every feature of the JavaScript language may be familiar to the developer. |
| 5 | + |
| 6 | +In this guide we will be covering some JavaScript features, |
| 7 | +and how they are used in Ember applications. |
| 8 | + |
| 9 | +## Variable declarations |
| 10 | + |
| 11 | +A variable declaration, also called binding, is when you assign a value to a variable name. |
| 12 | +An example of declaring a variable containing the number 42 is like so: |
| 13 | + |
| 14 | +```javascript |
| 15 | +var myNumber = 42; |
| 16 | +``` |
| 17 | + |
| 18 | +JavaScript initially had two ways to declare variables, globally and `var`. |
| 19 | +With the release of ES2015, `const` and `let` were introduced. |
| 20 | +We will go through the different ways to declare a variable, |
| 21 | +also called bindings because they *bind* a value to a variable name, |
| 22 | +and why modern JavaScript tends to prefer `const` and `let`. |
| 23 | + |
| 24 | +### `var` |
| 25 | + |
| 26 | +Variable declarations using `var` exist in the entire body of the function where they are declared. |
| 27 | +This is called function-scoping, the existence of the `var` is scoped to the function. |
| 28 | +If you try to access a `var` outside of the function it is declared, |
| 29 | +you will get an error that the variable is not defined. |
| 30 | + |
| 31 | +For our example, we will declare a `var` named `name`. |
| 32 | +We will try to access it both inside the function and outside, |
| 33 | +and see the results we get: |
| 34 | + |
| 35 | +```javascript |
| 36 | +console.log(name); // ReferenceError: name is not defined |
| 37 | + |
| 38 | +function myFunction() { |
| 39 | + var name = "Tomster"; |
| 40 | + |
| 41 | + console.log(name); // "Tomster" |
| 42 | +} |
| 43 | +``` |
| 44 | + |
| 45 | +This also means that if you have an `if` or a `for` in your code and declare a `var` inside them, |
| 46 | +you can still access the variable outside of those blocks: |
| 47 | + |
| 48 | +```javascript |
| 49 | +console.log(name); // undefined |
| 50 | + |
| 51 | +if (true) { |
| 52 | + var name = "Tomster"; |
| 53 | + |
| 54 | + console.log(name); // "Tomster" |
| 55 | +} |
| 56 | +``` |
| 57 | + |
| 58 | +In the previous example, we can see that the first `console.log(name)` prints out `undefined` instead of the value. |
| 59 | +That is because of a feature of JavaScript called *hosting*. |
| 60 | +Any variable declaration is moved by the programming language to the top of the scope it belongs to. |
| 61 | +As we saw at the beginning, `var` is scoped to the function, |
| 62 | +so the previous example is the same as: |
| 63 | + |
| 64 | +```javascript |
| 65 | +var name; |
| 66 | +console.log(name); // undefined |
| 67 | + |
| 68 | +if (true) { |
| 69 | + name = "Tomster"; |
| 70 | + |
| 71 | + console.log(name); // "Tomster" |
| 72 | +} |
| 73 | +``` |
| 74 | + |
| 75 | +### `const` and `let` |
| 76 | + |
| 77 | +There are two major differences between `var` and both `const` and `let`. |
| 78 | +`const` and `let` are both block-level declarations, and they are *not* hoisted. |
| 79 | + |
| 80 | +Because of this they are not accessible outside of the given block scope (meaning in a `function` or in `{}`) they are declared in. |
| 81 | +You can also not access them before they are declared, or you will get a [`ReferenceError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError). |
| 82 | + |
| 83 | +```javascript |
| 84 | +console.log(name) // ReferenceError: name is not defined |
| 85 | + |
| 86 | +if (person) { |
| 87 | + console.log(name) // ReferenceError: name is not defined |
| 88 | + |
| 89 | + let name = 'Gob Bluth'; // "Gob Bluth" |
| 90 | +} else { |
| 91 | + console.log(name) // ReferenceError: name is not defined |
| 92 | +} |
| 93 | +``` |
| 94 | + |
| 95 | +`const` declaration have an additional restriction, they are *constant references*, |
| 96 | +they always refer to the same thing. |
| 97 | +To use a `const` declaration you have to specify the value it refers, |
| 98 | +and you cannot change what the declaration refers to: |
| 99 | + |
| 100 | +```javascript |
| 101 | +const firstName; // Uncaught SyntaxError: Missing initializer in const declaration |
| 102 | +const firstName = 'Gob'; |
| 103 | +firstName = 'George Michael'; // Uncaught SyntaxError: Identifier 'firstName' has already been declared |
| 104 | +``` |
| 105 | + |
| 106 | +Note that `const` does not mean that the value it refers to cannot change. |
| 107 | +If you have an array or an object, you can change their properties: |
| 108 | + |
| 109 | +```javascript |
| 110 | +const myArray = []; |
| 111 | +const myObject = { name: "Tom Dale" }; |
| 112 | + |
| 113 | +myArray.push(1); |
| 114 | +myObject.name = "Leah Silber"; |
| 115 | + |
| 116 | +console.log(myArray); // [1] |
| 117 | +console.log(myObject); // {name: "Leah Silber"} |
| 118 | +``` |
| 119 | + |
| 120 | +### `for` loops |
| 121 | + |
| 122 | +Something that might be confusing is the behaviour of `let` in `for` loops. |
| 123 | + |
| 124 | +As we saw before, `let` declarations are scoped to the block they belong to. |
| 125 | +In `for` loops, any variable declared in the for syntax belongs to the loop's block. |
| 126 | + |
| 127 | +Let's look at some code to see what this looks like. |
| 128 | +If you use `var`, this happens: |
| 129 | + |
| 130 | +```javascript |
| 131 | +for (var i = 0; i < 3; i++) { |
| 132 | + console.log(i) // 0, 1, 2, 3 |
| 133 | +} |
| 134 | + |
| 135 | +console.log(i) // 3 |
| 136 | +``` |
| 137 | + |
| 138 | +But if you use `let`, this happens instead: |
| 139 | + |
| 140 | +```javascript |
| 141 | +for (let i = 0; i < 3; i++) { |
| 142 | + console.log(i) // 0, 1, 2, 3 |
| 143 | +} |
| 144 | + |
| 145 | +console.log(i) // ReferenceError: i is not defined |
| 146 | +``` |
| 147 | + |
| 148 | +Using `let` will avoid accidentally leaking and changing the `i` variable from outside of the `for` block. |
| 149 | + |
| 150 | +### Resources |
| 151 | + |
| 152 | +For further reference you can consult Developer Network articles: |
| 153 | + |
| 154 | +* [`var`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var) |
| 155 | +* [`const`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const) |
| 156 | +* [`let`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let). |
0 commit comments