Skip to content

Commit

Permalink
Yes, we are working on it.
Browse files Browse the repository at this point in the history
  • Loading branch information
BonsaiDen committed Feb 23, 2011
1 parent e3cef12 commit 6cc502e
Show file tree
Hide file tree
Showing 40 changed files with 2,594 additions and 327 deletions.
16 changes: 16 additions & 0 deletions doc/de/index.json
@@ -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"
]
}
]
}
13 changes: 13 additions & 0 deletions doc/de/intro/authors.md
@@ -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

8 changes: 8 additions & 0 deletions doc/de/intro/contributors.md
@@ -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

4 changes: 4 additions & 0 deletions doc/de/intro/index.md
@@ -0,0 +1,4 @@
## Einführung

Übersetzen.

12 changes: 12 additions & 0 deletions doc/de/intro/license.md
@@ -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

27 changes: 27 additions & 0 deletions doc/en/array/constructor.md
@@ -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.

60 changes: 60 additions & 0 deletions doc/en/array/general.md
@@ -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.

48 changes: 48 additions & 0 deletions doc/en/core/eval.md
@@ -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`.

114 changes: 114 additions & 0 deletions doc/en/core/semicolon.md
@@ -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.

69 changes: 69 additions & 0 deletions doc/en/core/undefined.md
@@ -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`.

0 comments on commit 6cc502e

Please sign in to comment.