Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
40 changed files
with
2,594 additions
and
327 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"title": "JavaScript Garden", | ||
"langTitle": "JavaScript Garden auf Deutsch", | ||
"description": "Ein Guide zu JavaScript Ecken und Kanten.", | ||
"sections": [ | ||
{ | ||
"title": "Einführung", | ||
"dir": "intro", | ||
"articles": [ | ||
"authors", | ||
"contributors", | ||
"license" | ||
] | ||
} | ||
] | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
## The Authors | ||
|
||
This guide is the work of two lovely Stack Overflow users, [Ivo Wetzel][1] | ||
(Writing) and [Zhang Yi Jiang][2] (Design). | ||
|
||
In case you are interested in additional guidance or reviews concerning your JavaScript | ||
projects, Ivo Wetzel offers these on a freelance basis. Please feel free to | ||
contact him via [e-mail][3] for further details. | ||
|
||
[1]: http://stackoverflow.com/users/313758/yi-jiang | ||
[2]: http://stackoverflow.com/users/170224/ivo-wetzel | ||
[3]: mailto:ivo.wetzel@googlemail.com | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
## Contributors | ||
|
||
- [Caio Romão][1] (Spelling corrections) | ||
- [Andreas Blixt][2] (Language corrections) | ||
|
||
[1]: https://github.com/caio | ||
[2]: https://github.com/blixt | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
## Einführung | ||
|
||
Übersetzen. | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
## License | ||
|
||
JavaScript Garden is published under the [MIT license][1] and hosted on | ||
[GitHub][2]. If you find errors or typos please [file an issue][3] or a pull | ||
request on the repository. You can also find us in the [JavaScript room][4] on | ||
Stack Overflow chat. | ||
|
||
[1]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE | ||
[2]: https://github.com/BonsaiDen/JavaScript-Garden | ||
[3]: https://github.com/BonsaiDen/JavaScript-Garden/issues | ||
[4]: http://chat.stackoverflow.com/rooms/17/javascript | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
## The `Array` Constructor | ||
|
||
Since the `Array` constructor is ambiguous in how it deals with its parameters, | ||
it is recommended to always use the `[]` notation when creating new arrays. | ||
|
||
[1, 2, 3]; // Result: [1, 2, 3] | ||
new Array(1, 2, 3); // Result: [1, 2, 3] | ||
|
||
[3]; // Result: [3] | ||
new Array(3); // Result: [undefined, undefined, undefined] | ||
new Array('3') // Result: ['3'] | ||
|
||
In cases when there is only one argument being passed to the `Array` constructor, | ||
and that argument is a `Number`, the constructor will use that number as the | ||
*length* of the new array to be created. | ||
|
||
This behavior only comes in handy in a few cases, like repeating a string, in | ||
which it avoids the use of a `for` loop. | ||
|
||
new Array(count + 1).join(stringToRepeat); | ||
|
||
### In Conclusion | ||
|
||
The use of the `Array` constructor should be avoided as much as possible. The `[]` | ||
notation is definitely preferred. It is shorter and has a clearer syntax; thus, | ||
it also increases the readability of code. | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
## Array Iteration and Properties | ||
|
||
Although arrays in JavaScript are objects, there are no good reasons to use | ||
the [for in loop](#object.forinloop) in for iteration on them. In fact there are | ||
a number of good reasons **against** the use of `for in` on arrays. | ||
|
||
> **Note:** JavaScript arrays are **not** *associative arrays*. JavaScript only | ||
> has [objects](#object.general) for mapping keys to values. And while associative | ||
> arrays **preserve** order, objects do **not**. | ||
Since the `for in` loop enumerates all properties on the prototype chain and | ||
the only way to exclude those properties is to use | ||
[`hasOwnProperty`](#object.hasownproperty), it is already up to **twenty times** | ||
slower than a normal `for` loop. | ||
|
||
### Iteration | ||
|
||
In order to achieve the best performance when iterating over arrays, it is best | ||
to use the classic `for` loop. | ||
|
||
var list = [1, 2, 3, 4, 5, ...... 100000000]; | ||
for(var i = 0, l = list.length; i < l; i++) { | ||
console.log(list[i]); | ||
} | ||
|
||
There is one extra catch in the above example, which is the caching of the | ||
length of the array via `l = list.length`. | ||
|
||
Although the `length` property is defined on the array itself, there is still an | ||
overhead for doing the lookup on each iteration of the loop. And while recent | ||
JavaScript engines **may** apply optimization in this case, there is no way of | ||
telling whether the code will run on one of these newer engines or not. | ||
|
||
In fact, leaving out the caching may result in the loop being only **half as | ||
fast** as with the cached length. | ||
|
||
### The `length` Property | ||
|
||
While the *getter* of the `length` property simply returns the number of | ||
elements that are contained in the array, the *setter* can be used to | ||
**truncate** the array. | ||
|
||
var foo = [1, 2, 3, 4, 5, 6]; | ||
foo.length = 3; | ||
foo; // [1, 2, 3] | ||
|
||
foo.length = 6; | ||
foo; // [1, 2, 3] | ||
|
||
Assigning a smaller length does truncate the array, but increasing the length | ||
does not have any effect on the array. | ||
|
||
### In Conclusion | ||
|
||
For the best performance it is recommended to always use the plain `for` loop | ||
and cache the `length` property. The use of `for in` on an array is a sign of | ||
badly written code that is prone to bugs and bad performance. Additionally, | ||
never should any assumptions be made whether the JavaScript engine will apply | ||
optimization to the code or not. | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
## The Evil `eval` | ||
|
||
The `eval` function will execute a string of JavaScript code in the local scope. | ||
|
||
var foo = 1; | ||
function test() { | ||
var foo = 2; | ||
eval('foo = 3'); | ||
return foo; | ||
} | ||
test(); // 3 | ||
foo; // 1 | ||
|
||
But `eval` only executes in local scope when it is being called directly **and** | ||
the name of the function that was actually called is `eval`. | ||
|
||
var foo = 1; | ||
function test() { | ||
var foo = 2; | ||
var bar = eval; | ||
bar('foo = 3'); | ||
return foo; | ||
} | ||
test(); // 2 | ||
foo; // 3 | ||
|
||
The use of `eval` should be avoided at **all costs**. 99.9% of its "uses" can be | ||
achieved **without** it. | ||
|
||
### `eval` in Disguise | ||
|
||
The [timeout functions](#other.timeouts) `setTimeout` and `setInterval` can both | ||
take a string as their first argument. This string will **always** get executed | ||
in the global scope since `eval` is not being called directly in that case. | ||
|
||
### Security Issues | ||
|
||
Also, `eval` is a security problem as it executes **any** code given to it, | ||
it should be **NEVER** used with strings of unknown or untrusted origins. | ||
|
||
### In Conclusion | ||
|
||
`eval` is **EVIL**. It should never be used, any code that makes use of it is to | ||
be questioned in its workings and security. If something requires `eval` in | ||
order to work, it is to be considered as magic and should **not** be used in the | ||
first place, a **better** design should be used that does not require the use of | ||
`eval`. | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
## Automatic semicolon insertion | ||
|
||
Although JavaScript has C style syntax, it does **not** enforce the use of | ||
semicolons in the source code, it is possible to omit them. | ||
|
||
But JavaScript is not a semicolon-less language, it in fact needs the | ||
semicolons in order to understand the source code. Therefore the JavaScript | ||
parser **automatically** inserts them whenever it encounters a parse | ||
error due to a missing semicolon. | ||
|
||
var foo = function() { | ||
} // parse error, semicolon expected | ||
test() | ||
|
||
Insertion happens, and the parser tries again. | ||
|
||
var foo = function() { | ||
}; // no error, parser continues | ||
test() | ||
|
||
The automatic insertion of semicolon is considered to be one of **biggest** | ||
design flaws in the language as it *can* change the behavior of code. | ||
|
||
### How it works | ||
|
||
The code below has no semicolons in it, so it is up to the parser to decide where | ||
to insert them. | ||
|
||
(function(window, undefined) { | ||
function test(options) { | ||
log('testing!') | ||
|
||
(options.list || []).forEach(function(i) { | ||
|
||
}) | ||
|
||
options.value.test( | ||
'long string to pass here', | ||
'and another long string to pass' | ||
) | ||
|
||
return | ||
{ | ||
foo: function() {} | ||
} | ||
} | ||
window.test = test | ||
|
||
})(window) | ||
|
||
(function(window) { | ||
window.someLibrary = {} | ||
|
||
})(window) | ||
|
||
Below is the result of the parser's "guessing" game. | ||
|
||
(function(window, undefined) { | ||
function test(options) { | ||
|
||
// Not inserted, lines got merged | ||
log('testing!')(options.list || []).forEach(function(i) { | ||
|
||
}); // <- inserted | ||
|
||
options.value.test( | ||
'long string to pass here', | ||
'and another long string to pass' | ||
); // <- inserted | ||
|
||
return; <- inserted, breaks the return statement | ||
{ // treated as a block | ||
|
||
// a label and a single expression statement | ||
foo: function() {} | ||
}; // <- inserted | ||
} | ||
window.test = test; // <- inserted | ||
|
||
// The lines got merged again | ||
})(window)(function(window) { | ||
window.someLibrary = {}; //<- inserted | ||
|
||
})(window); //<- inserted | ||
|
||
> **Note:** The JavaScript parser does not "correctly" handle return statements | ||
> which are followed by a new line, while this is not neccessarily the fault of | ||
> the automatic semicolon insertion, it can still be an unwanted side-effect. | ||
The parser drastically changed the behavior of the code above, in certain cases | ||
it does the **wrong** thing. | ||
|
||
### Leading parenthesis | ||
|
||
In case of a leading parenthesis, the parse will **not** insert a semicolon. | ||
|
||
log('testing!') | ||
(options.list || []).forEach(function(i) {}) | ||
|
||
This code gets transformed into one line. | ||
|
||
log('testing!')(options.list || []).forEach(function(i) {}) | ||
|
||
Chances are **very** high that `log` does **not** return a function, therefore the | ||
above will yield `TypeError` saying that `undefined is not a function`. | ||
|
||
### In conclusion | ||
|
||
It is highly recommended to **never** omit semicolons, it is also advocated to | ||
keep braces on the same line with their corresponding statements and to never omit | ||
them for one single-line `if` / `else` statements. Both of these measures will | ||
not only improve the consistency of the code, they will also prevent the | ||
JavaScript parser from changing its behavior. | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
## `undefined` and `null` | ||
|
||
JavaScript has two distinct values for "nothing", the more useful of those two | ||
being `undefined`. | ||
|
||
### The value `undefined` | ||
|
||
`undefined` is a type with exactly one value: `undefined`. | ||
|
||
The language also defines a global variable that has the value of `undefined`, | ||
this variable is also called `undefined`. But this variable is **not** a constant, | ||
meaning that it can be easily overwritten which then leads to abstruse bugs. | ||
|
||
> **ES5 Note:** `undefined` in ECMAScript 5 is **no longer** *writable* in strict | ||
> mode, but its name can still be shadowed by for example a function with the name | ||
> `undefined`. | ||
Some examples for when the value `undefined` is returned: | ||
|
||
- Accessing the (unmodified) global variable `undefined` | ||
- Implicit returns of functions due to missing `return` statements | ||
- `return` statements which don't explicitly return anything | ||
- Lookups of non existent properties | ||
- Function parameters which don't had any explicit value passed | ||
- Anything that has been set to the value of `undefined` | ||
|
||
### The case of the "overridden" `undefined` | ||
|
||
Since the variable `undefined` only has the value of `undefined`, changing its | ||
value does not change the value of the **type** `undefined`. | ||
|
||
Still, in order to compare something against the value of `undefined` it is | ||
necessary to retrieve the value of `undefined` in the first place. | ||
|
||
In order to protect code against a possible overwritten `undefined` variable, a | ||
common technique used is to add an additional parameter to the encapsulation | ||
[anonymous wrapper](#scopes), which gets no argument passed to it. | ||
|
||
var undefined = 123; | ||
(function(something, foo, undefined) { | ||
// undefined in the local scope does | ||
// now again refer to the value | ||
|
||
})('Hello World', 42); | ||
|
||
Another way to achieve the same effect would be to use a declaration inside the | ||
wrapper. | ||
|
||
var undefined = 123; | ||
(function(something, foo) { | ||
var undefined; | ||
... | ||
|
||
})('Hello World', 42); | ||
|
||
The only difference being here, that this version results in 4 more bytes being | ||
used in case it is minified and there is no other `var` statement inside the | ||
anonymous wrapper. | ||
|
||
### Uses of `null` | ||
|
||
While `undefined` in the context of the JavaScript language is mostly used in | ||
the sense of a traditional null, the actual `null` (both a literal and a type) | ||
is more or less just another data type. | ||
|
||
It is used in some JavaScript internals (like declaring the end of the | ||
prototype chain by setting `Foo.prototype = null`), but in almost all cases it | ||
can be replaced by `undefined`. | ||
|
Oops, something went wrong.