Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Yes, we are working on it.

  • Loading branch information...
commit 6cc502ea143782abea28259dba07ea9a0b987fb2 1 parent e3cef12
@BonsaiDen authored
Showing with 2,594 additions and 327 deletions.
  1. +16 −0 doc/de/index.json
  2. +13 −0 doc/de/intro/authors.md
  3. +8 −0 doc/de/intro/contributors.md
  4. +4 −0 doc/de/intro/index.md
  5. +12 −0 doc/de/intro/license.md
  6. +27 −0 doc/en/array/constructor.md
  7. +60 −0 doc/en/array/general.md
  8. +48 −0 doc/en/core/eval.md
  9. +114 −0 doc/en/core/semicolon.md
  10. +69 −0 doc/en/core/undefined.md
  11. +118 −0 doc/en/function/arguments.md
  12. +97 −0 doc/en/function/closures.md
  13. +102 −0 doc/en/function/constructors.md
  14. +84 −0 doc/en/function/general.md
  15. +153 −0 doc/en/function/scopes.md
  16. +110 −0 doc/en/function/this.md
  17. +72 −0 doc/en/index.json
  18. +13 −0 doc/en/intro/authors.md
  19. +8 −0 doc/en/intro/contributors.md
  20. +15 −0 doc/en/intro/index.md
  21. +12 −0 doc/en/intro/license.md
  22. +51 −0 doc/en/object/forinloop.md
  23. +99 −0 doc/en/object/general.md
  24. +53 −0 doc/en/object/hasownproperty.md
  25. +116 −0 doc/en/object/prototype.md
  26. +150 −0 doc/en/other/timeouts.md
  27. +71 −0 doc/en/types/casting.md
  28. +74 −0 doc/en/types/equality.md
  29. +38 −0 doc/en/types/instanceof.md
  30. +85 −0 doc/en/types/typeof.md
  31. +1 −69 doc/index.json
  32. +31 −14 garden.jade
  33. +107 −27 garden.js
  34. +22 −0 site/de/index.html
  35. BIN  site/image/sidebar-icon.png
  36. +425 −169 site/index.html
  37. +5 −11 site/javascript/garden.js
  38. +6 −0 site/javascript/html5.js
  39. +1 −13 site/javascript/plugin.js
  40. +104 −24 site/style/garden.css
View
16 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"
+ ]
+ }
+ ]
+}
View
13 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
+
View
8 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
+
View
4 doc/de/intro/index.md
@@ -0,0 +1,4 @@
+## Einführung
+
+Übersetzen.
+
View
12 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
+
View
27 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.
+
View
60 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.
+
View
48 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`.
+
View
114 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.
+
View
69 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`.
+
View
118 doc/en/function/arguments.md
@@ -0,0 +1,118 @@
+## The `arguments` Object
+
+Every function scope in JavaScript can access the special variable `arguments`.
+This variable holds a list of all the arguments that were passed to the function.
+
+> **Note:** In case `arguments` has already been defined inside the function's
+> scope either via a `var` statement or being the name of a formal parameter,
+> the `arguments` object will not be created.
+
+The `arguments` object is **not** an `Array`. While it has some of the
+semantics of an array - namely the `length` property - it does not inherit from
+`Array.prototype` and is in fact an `Object`.
+
+Due to this, it is not possible to use standard array methods like `push`,
+`pop` or `slice` on `arguments`. While iteration with a plain `for` loop works
+just fine, it is necessary to convert it to a real `Array` in order to use the
+array like methods on it.
+
+### Converting to an array
+
+The code below will return a new `Array` containing all the elements of the
+`arguments` object.
+
+ Array.prototype.slice.call(arguments);
+
+This conversion is **slow**, it is **not** recommended to use it in performance
+critical sections of code.
+
+### Passing arguments
+
+The following is the recommended way of passing arguments from one function to
+another.
+
+ function foo() {
+ bar.apply(null, arguments);
+ }
+ function bar(a, b, c) {
+ // do stuff here
+ }
+
+Another trick is to use both `call` and `apply` together to create fast, unbound
+wrappers.
+
+ function Foo() {}
+
+ Foo.prototype.method = function(a, b, c) {
+ console.log(this, a, b, c);
+ };
+
+ // Create an unbound version of "method"
+ // It takes the parameters: this, arg1, arg2...argN
+ Foo.method = function() {
+
+ // Result: Foo.prototype.method.call(this, arg1, arg2... argN)
+ Function.call.apply(Foo.prototype.method, arguments);
+ };
+
+
+### Modification "magic"
+
+The `arguments` object creates getter and setter functions for both its properties
+as well as the function's formal parameters.
+
+As a result, changing the value of a formal parameter will also change the value
+of the corresponding property of the arguments object, and the other way around.
+
+ function foo(a, b, c) {
+ arguments[0] = 2;
+ a; // 2
+
+ b = 4;
+ arguments[1]; // 4
+
+ var d = c;
+ d = 9;
+ c; // 3
+ }
+ foo(1, 2, 3);
+
+### Performance myths and truths
+
+The `arguments` object is always created the only two exceptions being the cases
+where it is declared as a name inside of a function or one of its formal
+parameters. It does not matter whether it is used or not.
+
+Both getters and setters are **always** created; thus, using it has nearly
+no performance impact at all, especially not in real world code where there is
+more than an access to the arguments object properties.
+
+> **ES5 Note:** These getters and setters are not created in strict mode.
+
+However, there is one case which will drastically reduce the performance in
+modern JavaScript engines. That case is the use of `arguments.callee`.
+
+ function foo() {
+ arguments.callee; // do something with this function object
+ arguments.callee.caller; // and the calling function object
+ }
+
+ function bigLoop() {
+ for(var i = 0; i < 100000; i++) {
+ foo(); // Would normally be inlined...
+ }
+ }
+
+In the above code, `foo` can no longer be a subject to [inlining][1] since it
+needs to know about both itself and its caller. This not only defeats possible
+performance gains due to inlining, it also breaks encapsulation since the
+function may now be dependent on being called in a specific context.
+
+It is highly recommended to **never** make use of `arguments.callee` or any of
+its properties.
+
+> **ES5 Note:** In strict mode, `arguments.callee` will throw a `TypeError` since
+> its use has been deprecated.
+
+[1]: http://en.wikipedia.org/wiki/Inlining
+
View
97 doc/en/function/closures.md
@@ -0,0 +1,97 @@
+## Closures and References
+
+One of JavaScript's most powerful features is the availability of *closures*,
+this means that scopes **always** keep access to the outer scope they were
+defined in. Since the only scope that JavaScript has is the
+[function scope](#function.scopes), all functions, by default, act as closures.
+
+### Emulating Private Variables
+
+ function Counter(start) {
+ var count = start;
+ return {
+ increment: function() {
+ count++;
+ },
+
+ get: function() {
+ return count;
+ }
+ }
+ }
+
+ var foo = Counter(4);
+ foo.increment();
+ foo.get(); // 5
+
+Here, `Counter` returns **two** closures. The function `increment` as well as
+the function `get`. Both of these functions keep a **reference** to the scope of
+`Counter` and, therefore, always have access to the `count` variable that was
+defined in that very scope.
+
+### Why Private Variables Work
+
+Since it is not possible to reference or assign scopes in JavaScript, there is
+**no** way of accessing the variable `count` from the outside. The only way to
+interact with it is via the two closures.
+
+ var foo = new Counter(4);
+ foo.hack = function() {
+ count = 1337;
+ };
+
+The above code will **not** change the variable `count` in the scope of `Counter`,
+since `foo.hack` was not defined in **that** scope. It will instead create - or
+override - the *global* variable `count`.
+
+### Closures Inside Loops
+
+One often made mistake is to use closures inside of loops, as if they were
+copying the value of the loops index variable.
+
+ for(var i = 0; i < 10; i++) {
+ setTimeout(function() {
+ console.log(i);
+ }, 1000);
+ }
+
+The above will **not** output the numbers `0` through `9`, it will simply print
+the number `10` ten times.
+
+The *anonymous* function keeps a reference to `i` and at the time `console.log`
+gets called, the `for` loop has already finished and the value of `i` is now `10`.
+
+In order to get the desired behavior, it is necessary to create a **copy** of
+the value of `i`.
+
+### Avoiding the Reference Problem
+
+In order to copy the value of the loop its index variable, it is best to use an
+[anonymous wrapper](#function.scopes).
+
+ for(var i = 0; i < 10; i++) {
+ (function(e) {
+ setTimeout(function() {
+ console.log(e);
+ }, 1000);
+ })(i);
+ }
+
+The anonymous outer function gets called immediately with `i` as the first
+argument and will receive a copy of the **value** of `i` as its parameter `e`.
+
+The anonymous function that gets passed to `setTimeout` now has a reference to
+`e`, which value does **not** get changed by the loop.
+
+There is another possible way of achieving this; that is to return a function
+from the anonymous wrapper, which will then have the same behavior as the code
+above.
+
+ for(var i = 0; i < 10; i++) {
+ setTimeout((function(e) {
+ return function() {
+ console.log(e);
+ }
+ })(i), 1000)
+ }
+
View
102 doc/en/function/constructors.md
@@ -0,0 +1,102 @@
+## Constructors
+
+Constructors in JavaScript are yet again different from many other languages. Any
+function call that is preceded by the `new` keyword acts as a constructor.
+
+Inside the constructor (the called function) the value of `this` refers to a
+newly created `Object`. The [`prototype`](#object.prototype) of this **new**
+object is set to the `prototype` of the function object that was called.
+
+If the function that was called has no explicit `return` statement, then it
+implicitly returns the value of `this` (the new object). Otherwise it returns
+the value of the `return` statement, **but** only if the return value is an
+object.
+
+ function Foo() {
+ this.bla = 1;
+ }
+
+ Foo.prototype.test = function() {
+ console.log(this.bla);
+ };
+
+ var test = new Foo();
+
+The above calls `Foo` as constructor and sets the `prototype` of the newly
+created object to `Foo.prototype`.
+
+Keep in mind that if you do not use the `new` keyword the function will **not**
+return a new object. While it might still work due to the workings of
+[`this`](#function.this) in JavaScript, it will use the *global* object as the
+value of `this`.
+
+### Factories
+
+In order to be able to omit the `new` keyword, the constructor function has to
+explicitly return a value.
+
+ function Bar() {
+ var value = 1;
+ return {
+ method: function() {
+ return value;
+ }
+ }
+ }
+ Bar.prototype = {
+ foo: function() {}
+ };
+
+ new Bar();
+ Bar();
+
+Both these calls return the exact same thing, a newly create object which
+has a property called `method` which is a [Closure](#function.closures).
+
+Also note that the call `new Bar()` does **not** affect the prototype of the
+returned object. While the prototype will be set on the newly created object,
+`Bar` never returns that object.
+
+So in the above example there is no functional difference between using and
+omitting the `new` keyword.
+
+
+### Creating new objects via factories
+
+An often made recommendation is to **not** use `new` since forgetting the use of
+it may lead to a lot of bugs.
+
+In order to create new object one now has to use a factory and set up the new
+object inside it.
+
+ function Foo() {
+ var obj = {};
+ obj.value = 'blub';
+
+ var private = 2;
+ obj.someMethod = function(value) {
+ this.value = value;
+ }
+
+ obj.getPrivate = function() {
+ return private;
+ }
+ return obj;
+ }
+
+While the above is robust against forgetting to use `new` and makes the use of
+[private variables](#function.closures) certainly easier, it comes with some down sides.
+
+ 1. It uses more memory since the created objects do **not** share the methods
+ 2. In order to inherit the factory needs to copy all the methods from another
+ object
+ 3. It somehow goes against the spirit of the language, by dropping prototype
+ chain just because a left out `new` keyword can break code
+
+### In Conclusion
+
+While omitting the `new` keyword might lead to bugs, it is certainly **not** a
+reason to drop the use of prototypes altogether. In the end it comes down to
+which solution is better suited for the needs of the application, it is especially
+important to choose a specific style of object creation **and** stick with it.
+
View
84 doc/en/function/general.md
@@ -0,0 +1,84 @@
+## Function Declarations and Expressions
+
+Functions in JavaScript are first class objects, which means that they can be
+passed around like any other value. One common use of this feature is to pass
+an *anonymous function* as a callback to another, possibly asynchronous function.
+
+### The `function` declaration
+
+ function foo() {}
+
+The above function gets created **before** the execution of the program starts;
+thus, it is available *everywhere* in the scope it was *defined* in, even if
+called before the actual definition in the source.
+
+ foo(); // Works because foo was created before this code runs
+ function foo() {}
+
+### The `function` expression
+
+ var foo = function() {};
+
+The above assigns the unnamed and - *anonymous* - function to the variable `foo`.
+
+ foo; // 'undefined'
+ foo(); // this raises a TypeError
+ var foo = function() {};
+
+Due to the fact that `var` is a *statement*, which - just like the function
+declaration - creates the variable `foo` before the actual execution of the code
+starts, `foo` is already defined when the script gets executed.
+
+Since assignments only happens at runtime, the value of `foo` will default
+to [undefined](#undefined) before the corresponding code is executed.
+
+### Named function expression
+
+Another special case is the assignment of named functions.
+
+ var foo = function bar() {
+ bar(); // Works
+ }
+ bar(); // ReferenceError
+
+Here `bar` is not available in the outer scope, since the function only gets
+assigned to `foo`; however, inside of `bar` it **is** available. This is due to
+how [name resolution](#scopes) in JavaScript works, the name of the function
+is always made available in the local scope of the function itself.
+
+### The `var` statement
+
+ function test() {
+ if (foo) {
+ bar = 2;
+
+ } else {
+ var bar = 1;
+ }
+ return foo;
+ }
+
+ if (false) {
+ var foo = 1;
+ }
+
+Since there is **no** [block scope](#scopes) in JavaScript, the above will
+**not** assign the value `2` to the *global* variable `bar`. Instead, it will
+assign the value of `2` to the *local* variable `bar` of `test`.
+
+Also, while the statements inside the `if` block never get executed, the variable
+`foo` still gets created and defaults to the value of `undefined`; again, this
+is due to the lack of block scoping.
+
+### Order of parsing
+
+All `var` statements get parsed **before** `function` declarations; hence,
+subsequent statements will override the previous ones.
+
+ function foo() {}
+ var foo;
+
+ foo; // [function foo]
+ var foo = 2;
+ foo; // 2
+
View
153 doc/en/function/scopes.md
@@ -0,0 +1,153 @@
+## Scopes and Namespaces
+
+Although JavaScript deals fine with the syntax of two matching curly
+braces for blocks, it does **not** support block scope; hence, all that is left
+is in the language is *function scope*.
+
+ function test() { // a scope
+ for(var i = 0; i < 10; i++) { // not a scope
+ // count
+ }
+ console.log(i); // 10
+ }
+
+> **Note:** When not used in an assignment, return statement or as a function
+> argument, the `{...}` notation will get interpreted as a block statement and
+> **not** as an object literal. This, in conjunction with
+> [automatic insertion of semicolons](#semicolon), can lead to subtle errors.
+
+There are also no distinct namespaces in JavaScript. This means that everything
+gets defined in **one** globally shared namespace.
+
+Each time a variable is referenced, JavaScript will traverse upwards through all
+the scopes until it finds it. In the case that it reaches the global scope and
+still has not found the requested name, it will raise a `ReferenceError`.
+
+### The bane of global variables
+
+ // script A
+ foo = '42';
+
+ // script B
+ var foo = '42'
+
+The above two scripts do **not** have the same effect. Script A defines a
+variable called `foo` in the *global* scope and script B defines a `foo` in the
+*current* scope.
+
+Again, that is **not** at all the same effect, not using `var` can have major
+implications.
+
+ // global scope
+ var foo = 42;
+ function test() {
+ // local scope
+ foo = 21;
+ }
+ test();
+ foo; // 21
+
+Leaving out the `var` statement inside the function `test` will override the
+value of `foo`. While this might not seem like a big deal at first, having
+thousands of lines of JavaScript and not using `var` will introduce hard to
+track down bugs.
+
+ // global scope
+ var items = [/* some list */];
+ for(var i = 0; i < 10; i++) {
+ subLoop();
+ }
+
+ function subLoop() {
+ // scope of subLoop
+ for(i = 0; i < 10; i++) { // missing var statement
+ // do amazing stuff!
+ }
+ }
+
+The outer loop will terminate after the first call to `subLoop`, since `subLoop`
+overwrites the global value of `i`. Using a `var` for the second `for` loop would
+have easily avoided this error. The `var` statement should never be left out
+unless the desired effect **is** to affect the outer scope.
+
+### Local variables
+
+The only source for local variables in JavaScript are [function](#functions)
+parameters and variables that were declared via the `var` statement.
+
+ // global scope
+ var foo = 1;
+ var bar = 2;
+ var i = 2;
+
+ function test(i) {
+ // local scope of the function test
+ i = 5;
+
+ var foo = 3;
+ bar = 4;
+ }
+ test(10);
+
+While `foo` and `i` are local variables inside the scope of the function `test`,
+the assignment of `bar` will override the global variable with the same name.
+
+### Name resolution order
+
+All scopes in JavaScript - including the global one - have the name
+[this](#this) defined in them, which refers to the "current object".
+
+Function scopes also have the name [arguments](#arguments) defined, which
+contains the arguments that were passed to a function.
+
+For example, when trying to access a variable named `foo` inside the scope of a
+function, JavaScript will lookup the name in the following order:
+
+ 1. In case there's a `var foo` statement in the current scope use that.
+ 2. If one of the function parameters is named `foo` use that.
+ 3. If the function itself is called `foo` use that.
+ 4. Go to the next outer scope and start with **#1** again.
+
+> **Note:** Having a parameter called `arguments` will **override** the default
+> `arguments` object.
+
+### Namespaces
+
+A common problem of having only one global namespace is the likeliness of running
+into problems where variable names clash. In JavaScript, this problem can be
+easily avoided with the help of anonymous *function wrappers*.
+
+ (function() {
+ // a self contained "namespace"
+
+ window.foo = function() {
+ // an exposed closure
+ };
+
+ })(); // execute the function immediately
+
+
+Unnamed functions are considered [expressions](#functions); so in order to being
+callable, they must first be evaluated.
+
+ ( // evaluate the function inside the paranthesis
+ function() {}
+ ) // and return the function object
+ () // call the result of the evaluation
+
+There are other ways for evaluating and calling the function expression; which,
+while different in syntax, do the exact same thing.
+
+ // Two other ways
+ +function(){}();
+ (function(){}());
+
+### In conclusion
+
+It is recommended to always use an *anonymous wrapper* for encapsulating code in
+its own namespace. This does not only protect the code against name clashes, it
+also allows for better modularization.
+
+Additionally, the use of global variables is considered **bad practice**, any use
+of them indicates badly written code that is prone to errors and hard to maintain.
+
View
110 doc/en/function/this.md
@@ -0,0 +1,110 @@
+## How `this` Works
+
+JavaScript has a different concept of what `this` refers to than most other
+languages do. There are exactly **five** different ways in which the value of
+`this` can be bound in the language.
+
+### The Global Scope
+
+ this;
+
+When using `this` in global scope, it will simply refer to the *global* object.
+
+
+### Calling a Function
+
+ foo();
+
+Here `this` will again refer to the *global* object.
+
+> **ES5 Note:** In strict mode, `this` will **no longer** refer to the global
+> object. It will instead have the value of `undefined`.
+
+### Calling a Method
+
+ test.foo();
+
+In this example `this` will refer to `test`.
+
+### Calling a Constructor
+
+ new foo();
+
+A function call that is preceded by the `new` keyword acts as
+a [constructor](#function.constructors). Inside the function `this` will refer
+to a newly created `Object`.
+
+### Explicit Setting of `this`
+
+ function foo(a, b, c) {}
+
+ var bar = {};
+ foo.apply(bar, [1, 2, 3]); // array will expand to the below
+ foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3
+
+When using the `call` or `apply` methods of `Function.prototype`, the value of
+`this` inside the called function gets explicitly set to the first argument of
+the corresponding function call.
+
+In the above example the *method case* does **not** apply, and `this` inside of
+`foo` will be set to `bar`.
+
+> **Note:** `this` **cannot** be used to refer to the object inside of an `Object`
+> literal. So `var obj = {me: this}` will **not** result in `me` referring to
+> `obj`, since `this` only gets bound by one of the above five cases.
+
+### Common Pitfalls
+
+While most of these cases make sense, the first one is to be considered another
+mis-design of the language, as it **never** has any practical use.
+
+ Foo.method = function() {
+ function test() {
+ // this is set to the global object
+ }
+ test();
+ }
+
+A common misconception is that `this` inside of `test` refers to `Foo`, but it
+does **not**.
+
+In order to gain access to `Foo` from within `test` it is necessary to create a
+local variable inside of `method` which refers to `Foo`.
+
+ Foo.method = function() {
+ var that = this;
+ function test() {
+ // Use that instead of this here
+ }
+ test();
+ }
+
+`that` is just a normal name, but it is commonly used for the reference to an
+outer `this`. In combination with [closures](#function.closures), it can also
+be used to pass `this` values around.
+
+### Assigning methods
+
+Another thing that does **not** work in JavaScript is **assigning** a method
+reference to a variable.
+
+ var test = someObject.methodTest;
+ test();
+
+Again due to the first case `test` now acts like like a plain function call;
+therefore, `this` inside it will no longer refer to `someObject`.
+
+While the late binding of `this` might seem like a bad idea, it is in fact what
+makes [prototypical inheritance](#object.prototype) work.
+
+ function Foo() {}
+ Foo.prototype.method = function() {};
+
+ function Bar() {}
+ Bar.prototype = Foo.prototype;
+
+ new Bar().method();
+
+When `method` gets called on a instance of `Bar`, `this` will now refer to that
+instance.
+
View
72 doc/en/index.json
@@ -0,0 +1,72 @@
+{
+ "title": "JavaScript Garden",
+ "langTitle": "JavaScript Garden in English",
+ "description": "A Guide to JavaScript's Quirks and Flaws.",
+ "sections": [
+ {
+ "title": "Intro",
+ "dir": "intro",
+ "articles": [
+ "authors",
+ "contributors",
+ "license"
+ ]
+ },
+ {
+ "title": "Objects",
+ "dir": "object",
+ "articles": [
+ "general",
+ "prototype",
+ "hasownproperty",
+ "forinloop"
+ ]
+ },
+ {
+ "title": "Functions",
+ "dir": "function",
+ "articles": [
+ "general",
+ "this",
+ "closures",
+ "arguments",
+ "constructors",
+ "scopes"
+ ]
+ },
+ {
+ "title": "Arrays",
+ "dir": "array",
+ "articles": [
+ "general",
+ "constructor"
+ ]
+ },
+ {
+ "title": "Types",
+ "dir": "types",
+ "articles": [
+ "equality",
+ "typeof",
+ "instanceof",
+ "casting"
+ ]
+ },
+ {
+ "title": "Core",
+ "dir": "core",
+ "articles": [
+ "eval",
+ "undefined",
+ "semicolon"
+ ]
+ },
+ {
+ "title": "Other",
+ "dir": "other",
+ "articles": [
+ "timeouts"
+ ]
+ }
+ ]
+}
View
13 doc/en/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
+
View
8 doc/en/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
+
View
15 doc/en/intro/index.md
@@ -0,0 +1,15 @@
+## Intro
+
+**JavaScript Garden** is a growing collection of documentation about the most
+quirky parts of the JavaScript programming language. It gives advice to
+avoid common mistakes, subtle bugs, as well as performance issues and bad
+practices that non-expert JavaScript programmers may encounter on their
+endeavours into the depths of the language.
+
+JavaScript Garden does **not** aim to teach you JavaScript. Former knowledge
+of the language is strongly recommended in order to understand the topics covered
+in this guide. In order to learn the basics of the language, please head over to
+the excellent [guide][1] on the Mozilla Developer Network.
+
+[1]: https://developer.mozilla.org/en/JavaScript/Guide
+
View
12 doc/en/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
+
View
51 doc/en/object/forinloop.md
@@ -0,0 +1,51 @@
+## The `for in` Loop
+
+Just like the `in` operator, the `for in` loop also traverses the prototype
+chain when iterating over the properties of an object.
+
+> **Note:** The `for in` loop will **not** iterate over any properties that
+> have their `enumerable` attribute set to `false`; for example, the `length`
+> property of an array.
+
+ // Poisoning Object.prototype
+ Object.prototype.bar = 1;
+
+ var foo = {moo: 2};
+ for(var i in foo) {
+ console.log(i); // prints both bar and moo
+ }
+
+Since it is not possible to change the behavior of the `for in` loop itself, it
+is necessary to filter out the unwanted properties inside the loop body itself,
+this is done by using the [`hasOwnProperty`](#object.hasownproperty) method of
+objects.
+
+> **Note:** Since the `for in` always traverses the complete prototype chain, it
+> will get slower with each additional layer of inheritance added to an object.
+
+### Using `hasOwnProperty` for Filtering
+
+ // still the foo from above
+ for(var i in foo) {
+ if (foo.hasOwnProperty(i)) {
+ console.log(i);
+ }
+ }
+
+This version is the only correct one to use. Due to the use of `hasOwnPropery` it
+will **only** print out `moo`. When `hasOwnProperty` is left out, the code is
+prone to errors when the native prototypes (for example,
+`Object.prototype`) have been extended.
+
+One widely used framework which does this is [Prototype][1]. When this
+framework is included, `for in` loops that do not use `hasOwnProperty` are
+guaranteed to break.
+
+### Best Practices
+
+It is recommended to **always** use `hasOwnProperty`. Never should any
+assumptions be made about the environment the code is running in, or whether the
+native prototypes have been extended or not.
+
+[1]: http://www.prototypejs.org/
+
View
99 doc/en/object/general.md
@@ -0,0 +1,99 @@
+## Object Usage and Properties
+
+Everything in JavaScript acts like an object, with the only two exceptions being
+[`null`](#core.undefined) and [`undefined`](#core.undefined).
+
+ false.toString() // 'false'
+ [1, 2, 3].toString(); // '1,2,3'
+
+ function Foo(){}
+ Foo.bar = 1;
+ Foo.bar; // 1
+
+A common misconception is that number literals cannot be used as
+objects. That is because a flaw in JavaScript's parser tries to parse the *dot
+notation* on a number as a floating point literal.
+
+ 2.toString(); // raises SyntaxError
+
+There are a couple of workarounds which can be used in order make number
+literals act as object too.
+
+ 2..toString(); // the second point is correctly recognized
+ 2 .toString(); // note the space left to the dot
+ (2).toString(); // 2 is evaluated first
+
+### Objects as a Data Type
+
+Objects in JavaScript can also be used as a [*Hashmap*][1], they mainly consist
+of named properties mapping to values.
+
+Using the curly brace notation `{}` one can create a plain object. This new
+object [inherits](#object.prototype) from `Object.prototype` and has no
+[own properties](#object.hasownproperty) defined on it.
+
+ var foo = {}; // a new empty object
+
+ // a new object with a property called 'test' with value 12
+ var bar = {test: 12};
+
+### Accessing Properties
+
+The properties of an object can be accessed in two ways, via either the dot
+notation, or the square bracket notation.
+
+ var foo = {name: 'Kitten'}
+ foo.name; // kitten
+ foo['name']; // kitten
+
+ var get = 'name';
+ foo[get]; // kitten
+
+ foo.1234; // SyntaxError
+ foo['1234']; // works
+
+Both notations are identical in their workings, with the only difference being that
+the square bracket notation allows for dynamic setting of properties, as well as
+the use of property names that would otherwise lead to a syntax error.
+
+### Deleting Properties
+
+The only way to actually remove a property from an object is to use the `delete`
+operator; setting the property to `undefined` or `null` does **only** remove the
+value associated with the property, but not the key.
+
+ var obj = {
+ bar: 1,
+ foo: 2,
+ baz: 3
+ };
+ obj.bar = undefined;
+ obj.foo = null;
+ delete obj.baz;
+
+ for(var i in obj) {
+ if (obj.hasOwnProperty(i)) {
+ console.log(i, '' + obj[i]);
+ }
+ }
+
+The above outputs both `bar undefined` and `foo null` - only `baz` got actually
+removed and is therefore missing from the output.
+
+### Notation of Keys
+
+ var test = {
+ 'case': 'I am a keyword so I must be notated as a string',
+ delete: 'I am a keyword too so me' // raises SyntaxError
+ };
+
+Object properties can be both notated as plain characters and as strings. Due to
+another mis-design in JavaScript's parser, prior to ECMAScript 5 the above will throw
+a `SyntaxError`.
+
+This error arises from the fact that `delete` is a *keyword* of the language;
+therefore, it must be notated as a string literal in order to ensure working
+code under older JavaScript engines.
+
+[1]: http://en.wikipedia.org/wiki/Hashmap
+
View
53 doc/en/object/hasownproperty.md
@@ -0,0 +1,53 @@
+## `hasOwnProperty`
+
+In order to check whether a object has a property defined on itself and **not**
+somewhere on its [prototype chain](#object.prototype), it is necessary to use the
+`hasOwnProperty` method which all objects inherit from `Object.prototype`.
+
+> **Note:** It is **not** enough to check whether a property is `undefined`. The
+> property might very well exist, but its value just happens to be set to
+> `undefined`.
+
+`hasOwnProperty` is the only thing in JavaScript which deals with properties and
+does **not** traverse the prototype chain.
+
+ // Poisoning Object.prototype
+ Object.prototype.bar = 1;
+ var foo = {goo: undefined};
+
+ foo.bar; // 1
+ 'bar' in foo; // true
+
+ foo.hasOwnProperty('bar'); // false
+ foo.hasOwnProperty('goo'); // true
+
+Only `hasOwnProperty` will give the correct and expected result. This is
+essential when iterating over the properties of any object. There is no other
+way to exclude properties that are not defined on the object **itself**, but
+somewhere on its prototype chain.
+
+### `hasOwnProperty` as a Property
+
+JavaScript does not protect the property name `hasOwnProperty`; therefore, if the
+possibility exists that an object might have a property with this name, it is
+necessary to use an *external* `hasOwnProperty` in order to get correct results.
+
+ var foo = {
+ hasOwnProperty: function() {
+ return false;
+ },
+ bar: 'Here be dragons'
+ };
+
+ foo.hasOwnProperty('bar'); // always returns false
+
+ // Use another hasOwnProperty and call it with 'this' set to foo
+ {}.hasOwnProperty.call(foo, 'bar'); // true
+
+### In Conclusion
+
+When checking for the existence of a property on a object, `hasOwnProperty` is
+the **only** method of doing so. It is also recommended to make `hasOwnProperty`
+part of **every** [`for in` loop](#object.forinloop), this will avoid errors from
+extended native [prototypes](#object.prototype).
+
View
116 doc/en/object/prototype.md
@@ -0,0 +1,116 @@
+## The Prototype
+
+JavaScript does not feature the classical inheritance model, instead it uses a
+*prototypical* one.
+
+While this is often considered to be one of JavaScript's weaknesses, the
+prototypical inheritance model is in fact more powerful than the classic model.
+For example, it is fairly trivial to build a classic model on top of it, while
+the other way around is a far more difficult task.
+
+Due to the fact that JavaScript is basically the only widely used language that
+features prototypical inheritance, it takes some time to adjust to the
+differences between the two models.
+
+The first major difference is that inheritance in JavaScript is done by using so
+called *prototype chains*.
+
+> **Note:** Simply using `Bar.prototype = Foo.prototype` will result in both objects
+> sharing the **same** prototype. Therefore, changes to either object its prototype
+> will affect the other its prototype as well, which in most cases is not the
+> desired effect.
+
+ function Foo() {
+ this.value = 42;
+ }
+ Foo.prototype = {
+ method: function() {}
+ };
+
+ function Bar() {}
+
+ // Set Bar's prototype to a new instance of Foo
+ Bar.prototype = new Foo();
+ Bar.prototype.foo = 'Hello World';
+
+ // Make sure to list Bar as the actual constructor
+ Bar.prototype.constructor = Bar;
+
+ var test = new Bar() // create a new bar instance
+
+ // The resulting prototype chain
+ test [instance of Bar]
+ Bar.prototype [instance of Foo]
+ { foo: 'Hello World' }
+ Foo.prototype
+ {method: ...}
+ Object.prototype
+ { toString: ... /* etc. */ }
+
+In the above, the object `test` will inherit from both `Bar.prototype` and
+`Foo.prototype`; hence, it will have access to the function `method` that was
+defined on `Foo`. But it will not have access to the property `value` of a
+`Foo` instance, since that property gets defined in the
+[constructor](#function.constructor) of `Foo`. But this constructor has to be
+called explicitly.
+
+> **Note:** Do **not** use `Bar.prototype = Foo`, since it will not point to
+> the prototype of `Foo` but rather to the function object `Foo`. So the
+> prototype chain will go over `Function.prototype` and not `Foo.prototype`;
+> therefore, `method` will not be on the prototype chain.
+
+### Property Lookup
+
+When accessing the properties of an object, JavaScript will traverse the
+prototype chain **upwards** until it finds a property with the requested name.
+
+When it reaches the top of the chain - namely `Object.prototype` - and still
+hasn't found the specified property, it will return the value
+[undefined](#core.undefined) instead.
+
+### The Prototype Property
+
+While the prototype property is used by the language to build the prototype
+chains, it is still possible to assign **any** given value to it. Although
+primitives will simply get ignored when assigned as a prototype.
+
+ function Foo() {}
+ Foo.prototype = 1; // no effect
+
+Assigning objects, as shown in the example above, will work, and allows for
+dynamic creation of prototype chains.
+
+### Performance
+
+The lookup time for properties that are high up on the prototype chain can have a
+negative impact on performance critical sections of code. Additionally, trying to
+access non-existent properties will always traverse the full prototype chain.
+
+Also, when [iterating](#object.forinloop) over the properties of an object
+**every** property that is on the prototype chain will get enumerated.
+
+### Extension of Native Prototypes
+
+One mis-feature that is often used is to extend `Object.prototype` or one of the
+other built in prototypes.
+
+This technique is called [monkey patching][1] and breaks *encapsulation*. While
+used by widely spread frameworks such as [Prototype][2], there is still no good
+reason for cluttering built in types with additional non-standard functionality.
+
+The **only** good reason for extending a built in prototype is to back port
+the features of newer JavaScript engines; for example,
+[`Array.forEach`][3].
+
+### In Conclusion
+
+It is a must to understand the prototypical inheritance model completely before
+writing complex code which makes use of it. Also, watching the length of the
+prototype chains and breaking them up if necessary can avoid possible performance
+issues. Further, the native prototypes should **never** be extended unless it is
+for the sake of compatibility with newer JavaScript features.
+
+[1]: http://en.wikipedia.org/wiki/Monkey_patch
+[2]: http://prototypejs.org/
+[3]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach
+
View
150 doc/en/other/timeouts.md
@@ -0,0 +1,150 @@
+### `setTimeout` and `setInterval`
+
+Since JavaScript is asynchronous, it is possible to schedule the execution of a
+function by using the `setTimeout` and `setInterval` functions.
+
+> **Note:** Timeouts are **not** part of the ECMAScript Standard, they are
+> implemented as part of the [Document Object Model][1].
+
+ function foo() {}
+ var id = setTimeout(foo, 1000); // returns a Number > 0
+
+When `setTimeout` gets called, it will return the ID of the timeout and schedule
+`foo` to run in **approximately** one thousand milliseconds in the future.
+`foo` will then executed exactly **once**.
+
+Depending on the timer resolution of the JavaScript engine that is running the
+code, as well as the fact that JavaScript is single threaded and other code that
+gets executed might block the thread, it is by no means a safe bet that one will
+get the exact timeout they specified when calling `setTimeout`.
+
+The function that was passed as the first parameter will get called by the
+global object, that means that [this](#function.this) inside the called function
+refers to that very object.
+
+ function Foo() {
+ this.value = 42;
+ this.method = function() {
+ // this refers to the global object
+ console.log(this.value); // will log undefined
+ };
+ setTimeout(this.method, 500);
+ }
+ new Foo();
+
+
+> **Note:** As `setTimeout` takes a **function object** as its first parameter, an
+> often made mistake is to use `setTimeout(foo(), 1000)`, which will use the
+> **return value** of the call `foo` and **not** `foo`. This is, most of the time,
+> a silent error, since when the function returns `undefined` `setTimeout` will
+> **not** raise any error.
+
+### Stacking Calls with `setInterval`
+
+While `setTimeout` only runs the function once, `setInterval` - as the name
+suggests - will execute the function **every** `X` milliseconds. But its use is
+discouraged.
+
+When code that is being executed blocks the timeout call, `setInterval` will
+still issue more calls to the specified function. This can, especially with small
+intervals, result in function calls stacking up.
+
+ function foo(){
+ // something that blocks for 1 second
+ }
+ setInterval(foo, 100);
+
+In the above code `foo` will get called once and will then block for one second.
+
+While `foo` blocks the code `setInterval` will still schedule further calls to
+it. Now, when `foo` has finished, there will already be **ten** further calls to
+it waiting for execution.
+
+### Dealing with Possible Blocking Code
+
+The easiest as well as most controllable solution, is to use `setTimeout` within
+the function itself.
+
+ function foo(){
+ // something that blocks for 1 second
+ setTimeout(foo, 100);
+ }
+ foo();
+
+Not only does this encapsulate the `setTimeout` call, but it also prevents the
+stacking of calls and it gives additional control.`foo` itself can now decide
+whether it wants to run again or not.
+
+### Manually Clearing Timeouts
+
+Clearing timeouts and intervals works by passing the respective ID to
+`clearTimeout` or `clearInterval`, depending which `set` function was used in
+the first place.
+
+ var id = setTimeout(foo, 1000);
+ clearTimeout(id);
+
+### Clearing all Timeouts
+
+As there is no built in method for clearing all timeouts and/or intervals,
+it is necessary to use brute force in order to achieve this functionality.
+
+ // clear "all" timeouts
+ for(var i = 1; i < 1000; i++) {
+ clearTimeout(i);
+ }
+
+There might still be timeouts that are unaffected by this arbitrary number;
+therefore, is is instead recommended to keep track of all the timeout IDs, so
+they can be cleared one by one.
+
+### Hidden `eval` Magic
+
+`setTimeout` and `setInterval` can also take a string as their first parameter.
+This feature should **never** be used, since it internally makes use of `eval`.
+
+ function foo() {
+ // will get called
+ }
+
+ function bar() {
+ function foo() {
+ // never gets called
+ }
+ setTimeout('foo()', 1000);
+ }
+ bar();
+
+Since `eval` is not getting [called directly](#core.eval) here, the string passed
+to `setTimeout` will get executed in the global scope; thus, it will not use the
+local variable `foo` from the scope of `bar`.
+
+It is further recommended to **not** use a string to pass arguments to the
+function that will get called.
+
+ function foo(a, b, c) {}
+
+ // NEVER use this
+ setTimeout('foo(1,2, 3)', 1000)
+
+ // Instead use an anonymous function
+ setTimeout(function() {
+ foo(a, b, c);
+ }, 1000)
+
+> **Note:** While it is also possible to use the syntax
+> `setTimeout(foo, 1000, a, b, c)`, it is not recommended, as its use may lead
+> to subtle errors when used with [methods](#function.this).
+
+### In Conclusion
+
+**Never** should a string be used as the parameter of `setTimeout` or
+`setInterval`. It is a clear sign of **really** bad code, when arguments need
+to be supplied to the function that gets called, an anonymous function should
+be passed which handles the actual calling.
+
+Additionally, `setInterval` should be avoided since it is hard to control and
+does not adjust to the single threaded nature of the language.
+
+[1]: http://en.wikipedia.org/wiki/Document_Object_Model
+
View
71 doc/en/types/casting.md
@@ -0,0 +1,71 @@
+## Type casting
+
+JavaScript is a *weakly typed* language, so it will apply *type coercion*
+wherever possible.
+
+ // These are true
+ new Number(10) == 10; // Number.toString() is converted
+ // back to a number
+
+ 10 == '10'; // Strings gets converted to Number
+ 10 == '+10 '; // More string madness
+ 10 == '010'; // And more
+ isNaN(null) == false; // null converts to 0
+ // which of course is not NaN
+
+ // These are false
+ 10 == 010;
+ 10 == '-10';
+
+> **ES5 Note:** Number literals that start with a `0` are interpreted as octal
+> (Base 8). Octal support for these has been **removed** in ECMAScript 5 strict
+> mode.
+
+In order to avoid that the use of the [strict equal operator](#equality) is
+recommended.
+
+But this does still not solve all the issues that arise from JavaScript's weak
+typing system.
+
+### Madness with `new` and built in types
+
+The constructors of the built in types like `Number` and `String` behave
+differently when being used with the `new` keyword and without it.
+
+ new Number(10) === 10; // False, Object and Number
+ Number(10) === 10; // True, Number and Number
+ new Number(10) + 0 === 10; // True, due to implicit conversion
+
+Using the built in type like `Number` as a constructor will create a new number
+`Object`, but leaving out the `new` keyword will make it behave like a converter.
+
+In addition, having literals or non `Object` values in there will activate more
+coercing magic.
+
+The best option is to do cast to one of the three possible types explicitly.
+
+### Casting to a string
+
+ '' + 10 === '10'; // true
+
+By using a empty string a value can easily be casted to a plain string.
+
+### Casting to a number
+
+ +'10' === 10; // true
+
+Using the **unary** plus operator it is possible to cast to a plain number.
+
+### Casting to a boolean
+
+By using the **not** operator twice, a value can be converted to its boolean
+value.
+
+ !!'foo'; // true
+ !!''; // false
+ !!'0'; // false
+ !!'1'; // true
+ !!'-1' // true
+ !!{}; // true
+ !!true; // true
+
View
74 doc/en/types/equality.md
@@ -0,0 +1,74 @@
+## Equality and Comparisons
+
+JavaScript has two different ways of comparing the values of objects for else
+equality.
+
+### The Equals Operator
+
+The equals operator consists of two equal signs: `==`
+
+JavaScript features *weak typing*, that means, the equals operator does
+**coerce** types in order to compare them.
+
+ "" == "0" // false
+ 0 == "" // true
+ 0 == "0" // true
+ false == "false" // false
+ false == "0" // true
+ false == undefined // false
+ false == null // false
+ null == undefined // true
+ " \t\r\n" == 0 // true
+
+The above table shows the results of the type coercion and it is the main reason
+why the use of `==` is regarded as bad practice, it introduces hard to track down
+bugs due to its complicated conversion rules.
+
+Additionally there is also a performance impact when type coercion is in play;
+for example, a string has to be converted to a number before it can be compared
+with another number.
+
+### The Strict Equals Operator
+
+The strict equals operator consists of **three** equal signs: `===`
+
+Other than the normal equals operator, the strict equals operator does **not**
+coerce the types of its operands.
+
+ "" === "0" // false
+ 0 === "" // false
+ 0 === "0" // false
+ false === "false" // false
+ false === "0" // false
+ false === undefined // false
+ false === null // false
+ null === undefined // false
+ " \t\r\n" === 0 // false
+
+The above results not only make a lot more sense, they also get rid of most of
+the weak typing in the language. This makes writing code a lot easier since
+things will break earlier and a lot of subtle bugs can be avoided.
+
+It will also be a lot faster when the operands are of different types.
+
+### Comparing Objects
+
+While both `==` and `===` are stated as **equality** operators, they behave
+different when at least one of their operands happens to be an `Object`.
+
+ {} === {}; // false
+ new String('foo') === 'foo'; // false
+ new Number(10) === 10; // false
+ var foo = {};
+ foo === foo; // true
+
+Here both operators compare for **identity** and not equality - that is, they
+will compare for the same **instance** of the object, much like `is` in Python
+and a pointer comparison in C do.
+
+### In cConclusion
+
+It is highly recommended to **only** use the strict equals operator. In cases
+where types need to be coerced, it should be done [explicitly](#types.casting)
+and not left to the "magic" of the languages complicated coercing rules.
+
View
38 doc/en/types/instanceof.md
@@ -0,0 +1,38 @@
+## The `instanceof` Operator
+
+The `instanceof` operator compares the constructors of its two operands. It is
+only useful when comparing custom made objects. Using it on built in types is
+nearly as useless as the [typeof operator](#types.typeof).
+
+### Comparing Custom Objects
+
+ function Foo() {}
+ function Bar() {}
+ Bar.prototype = new Foo();
+
+ new Bar() instanceof Bar; // true
+ new Bar() instanceof Foo; // true
+
+ // This just sets Bar.prototype to the function object Foo
+ // But not to an actual instance of Foo
+ Bar.prototype = Foo;
+ new Bar() instanceof Foo; // false
+
+### Using `instanceof` with Native Types
+
+ new String('foo') instanceof String; // true
+ new String('foo') instanceof Object; // true
+
+ 'foo' instanceof String; // false
+ 'foo' instanceof Object; // false
+
+One important thing to note is that `instanceof` does of course not work on
+objects that origin from different JavaScript contexts (e.g. different documents
+in a web browser), since their constructors will not be the exact same object.
+
+### In Conclusion
+
+The `instanceof` operator should **only** be used when dealing with custom made
+objects that origin from the same JavaScript context. Just like the
+[`typeof`](#types.typeof) operator, every other use of it should be **avoided**.
+
View
85 doc/en/types/typeof.md
@@ -0,0 +1,85 @@
+## The `typeof` Operator
+
+The `typeof` operator (together with
+[`instanceof`](#instanceof)) is probably the biggest
+design flaw of JavaScript, as it is near of being **completely broken**.
+
+Although `instanceof` still has its limited uses, `typeof` really has only one
+practical use case, which does **not** happen to be checking the type of an
+object.
+
+> **Note:** While `typeof` can also be called with a function like syntax
+> i.e. `typeof(obj)`, this is not a function call. The two parenthesis will
+> behave like normal and there return value will be used as the operand of the
+> `typeof` operator. There is **no** `typeof` function.
+
+### The JavaScript type table
+
+ Value Class Type
+ -------------------------------------
+ "foo" String string
+ new String("foo") String object
+ 1.2 Number number
+ new Number(1.2) Number object
+ true Boolean boolean
+ new Boolean(true) Boolean object
+ new Date() Date object
+ new Error() Error object
+ [1,2,3] Array object
+ new Array(1, 2, 3) Array object
+ new Function("") Function function
+ /abc/g RegExp object (function in Nitro/V8)
+ new RegExp("meow") RegExp object (function in Nitro/V8)
+ {} Object object
+ new Object() Object object
+
+In the above table *Type* refers to the value the `typeof` operator returns. As
+you can see this is anything but consistent.
+
+The *Class* refers to the value of the internal `[[Class]]` property of an object.
+
+> **From the Specification:** The value of `[[Class]]` can be one of the
+> following strings. `Arguments`, `Array`, `Boolean`, `Date`, `Error`,
+> `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`.
+
+In order to retrieve the value of `[[Class]]` one can has to make use of the
+`toString` method of `Object`.
+
+### The Class of an object
+
+The specification gives exactly one way of accessing the `[[Class]]` value,
+which the use of `Object.prototype.toString`.
+
+ function is(type, obj) {
+ var clas = Object.prototype.toString.call(obj).slice(8, -1);
+ return obj !== undefined && obj !== null && clas === type;
+ }
+
+ is('String', 'test'); // true
+ is('String', new String('test')); // true
+
+In the above example, `Object.prototype.toString` gets called with the value of
+[this](#this) being set to the object whose `[[Class]]` value should be retrieved.
+
+> **ES5 Note:** For convenience the return value of `Object.prototype.toString`
+> for both null` and `undefined` was **changed** from `Object` to `Null` and
+> `Undefined` in ECMAScript 5.
+
+### Testing for undefined variables
+
+ typeof foo !== 'undefined'
+
+The above will check whether `foo` was actually declared or not; just
+referencing it would result in a `ReferenceError`. This is the only thing
+`typeof` is actually useful for.
+
+### In conclusion
+
+In order to check the type of an object, it is highly recommended to use
+`Object.prototype.toString`; as this is the only reliable way of doing so.
+As shown in the above type table, some return values of `typeof` are not defined
+in the specification; thus, they can differ across various implementations.
+
+Unless checking whether a variable is defined, `typeof` should be avoided at
+**all costs**.
+
View
70 doc/index.json
@@ -1,71 +1,3 @@
{
- "title": "JavaScript Garden",
- "description": "A Guide to JavaScript's Quirks and Flaws.",
- "sections": [
- {
- "title": "Intro",
- "dir": "intro",
- "articles": [
- "authors",
- "contributors",
- "license"
- ]
- },
- {
- "title": "Objects",
- "dir": "object",
- "articles": [
- "general",
- "prototype",
- "hasownproperty",
- "forinloop"
- ]
- },
- {
- "title": "Functions",
- "dir": "function",
- "articles": [
- "general",
- "this",
- "closures",
- "arguments",
- "constructors",
- "scopes"
- ]
- },
- {
- "title": "Arrays",
- "dir": "array",
- "articles": [
- "general",
- "constructor"
- ]
- },
- {
- "title": "Types",
- "dir": "types",
- "articles": [
- "equality",
- "typeof",
- "instanceof",
- "casting"
- ]
- },
- {
- "title": "Core",
- "dir": "core",
- "articles": [
- "eval",
- "undefined",
- "semicolon"
- ]
- },
- {
- "title": "Other",
- "dir": "other",
- "articles": [
- "timeouts"
- ]
- }
- ]
+ "default": "en"
}
View
45 garden.jade
@@ -4,26 +4,47 @@ html(lang='en')
title #{title}
meta(charset='utf-8')
meta(name='description', content=description)
- link(rel='stylesheet', href='style/garden.css', media='all')
- link(rel='stylesheet', href='style/print.css', media='print')
+
+ - if (language === baseLanguage)
+ link(rel='stylesheet', href='style/garden.css', media='all')
+ link(rel='stylesheet', href='style/print.css', media='print')
+
+ - else
+ link(rel='stylesheet', href='../style/garden.css', media='all')
+ link(rel='stylesheet', href='../style/print.css', media='print')
+
+ <!--[if lt IE 9]>
+ <script src="/javascript/html5.js"></script>
+ <![endif]-->
body
// Navigation
nav
+ div
+ ul
+ - each lang in languages
+ li(class=lang.id === language ? 'active' : '')
+ - if (lang.id === baseLanguage)
+ a(href= '/', title=lang.title) #{lang.id}
+
+ - else
+ a(href= '/' + lang.id, title=lang.title) #{lang.id}
ul
- each section in navigation
- li
+ li(class='nav_' + section.link.replace(/\./g, '_'))
h1
a(href='#' + section.link) #{section.title}
- ul
- li
- a(href='#' + section.link + '.intro') Overview
-
- - each article in section.articles
- li
- a(href='#' + article.link)!=article.title
+ - if (section.parsed.index || section.articles.length > 0)
+ ul
+ - if (section.parsed.index )
+ li
+ a(href='#' + section.link + '.intro') Overview
+
+ - each article in section.articles
+ li
+ a(href='#' + article.link)!=article.title
// Sections
- each section in sections
@@ -35,10 +56,6 @@ html(lang='en')
- if (section.parsed.index)
div!=section.parsed.index.text
- - else
- div
- strong TODO: Add section intro in "doc/#{section.dir}/index.md"
-
// Articles
- each article in section.articles
article(id=article.link)
View
134 garden.js
@@ -1,28 +1,69 @@
-var fs = require('fs');
-var jade = require('jade');
-var md = require('node-markdown');
-var Class = require('neko').Class;
+var fs = require('fs'),
+ path = require('path');
+ jade = require('jade'),
+ md = require('node-markdown'),
+ Class = require('neko').Class;
+
+var format = new require('fomatto').Formatter();
// Garden Generator -------------------------------------------------------------
// ------------------------------------------------------------------------------
var Garden = Class(function(options) {
+ var languages = fs.readdirSync(options.dir);
+ this.languages = {};
this.options = options;
- this.index = this.json(this.options.dir + '/index.json');
- this.loadIndex();
+
+ var that = this;
+ languages.forEach(function(lang) {
+ if (fs.statSync(that.options.dir + '/' + lang).isDirectory()) {
+ that.log('Parsing language "{}"...', lang);
+ that.lang = {
+ id: lang,
+ navigation: [],
+ index: []
+ };
+
+ if (that.loadIndex()) {
+ that.languages[lang] = that.lang;
+ that.log(' Done.')
+
+ } else {
+ that.log(' Error: Could not find "index.json"!')
+ }
+ }
+ });
+
+ delete this.lang;
+ this.log('');
+ this.generateAll();
}, {
+ log: function() {
+ console.log(format.apply(null, arguments));
+ },
+
loadIndex: function() {
var that = this;
- this.navigation = [];
- this.index.sections.forEach(function(section, i) {
+ this.lang.index = this.json([this.options.dir,
+ this.lang.id, 'index.json'].join('/'));
+
+ if (this.lang.index === null) {
+ return false;
+ }
+
+ that.lang.title = that.lang.index.langTitle;
+ this.lang.navigation = [];
+ this.lang.index.sections.forEach(function(section, i) {
that.loadSection(section);
- that.navigation.push({
+ that.lang.navigation.push({
title: section.title,
link: section.dir,
- articles: section.articles
+ articles: section.articles,
+ parsed: section.parsed
});
});
+ return true;
},
loadSection: function(section) {
@@ -52,17 +93,18 @@ var Garden = Class(function(options) {
var title = text.substring(0, text.indexOf('\n'));
text = text.substring(title.length);
title = md.Markdown(title.replace(/\#/g, '').trim());
+ text = this.toMarkdown(text);
- var parts = text.split('###');
+ var parts = text.split('<h3>');
var subs = [];
for(var i = 0, l = parts.length; i < l; i++) {
var sub = parts[i];
- subs.push(this.toMarkdown((i > 0 ? '###' : '') + sub));
+ subs.push((i > 0 ? '<h3>' : '') + sub);
}
return {
title: title.substring(3, title.length - 4),
- text: this.toMarkdown(text),
+ text: text,
subs: subs
};
},
@@ -74,7 +116,12 @@ var Garden = Class(function(options) {
},
json: function(file) {
- return JSON.parse(fs.readFileSync(file).toString());
+ try {
+ return JSON.parse(fs.readFileSync(file).toString());
+
+ } catch (err) {
+ return null;
+ }
},
md: function(section, article) {
@@ -83,24 +130,57 @@ var Garden = Class(function(options) {
},
folder: function(section) {
- return [this.options.dir, section].join('/');
+ return [this.options.dir, this.lang.id, section].join('/');
},
- render: function(template, out) {
- var options = {
- title: this.index.title,
- description: this.index.description,
- navigation: this.navigation,
- sections: this.index.sections,
- top: this.navigation[0]
- };
+ render: function(language, template, out) {
+ var lang = this.languages[language];
+ if (lang) {
+ this.log('Rendering "{}" to "{}"...', language, out);
+ var options = {
+ baseLanguage: this.options.base,
+ language: language,
+ languages: this.languages,
+ title: lang.index.title,
+ description: lang.index.description,
+ navigation: lang.navigation,
+ sections: lang.index.sections,
+ top: lang.navigation[0]
+ };
+
+ jade.renderFile(template, {locals: options}, function(err, html){
+ if (err) throw err;
+ fs.writeFileSync(out, html);
+ });
+ this.log(' Done.');
+ }
+ },
+
+ generateAll: function() {
+ for(var i in this.languages) {
+ if (this.languages.hasOwnProperty(i)) {
+ this.generate(i);
+ }
+ }
+ },
+
+ generate: function(lang) {
+ var that = this;
- jade.renderFile(template, {locals: options}, function(err, html){
- if (err) throw err;
- fs.writeFileSync(out, html);
+ var dir = [this.options.out];
+ if (lang !== this.options.base) {
+ dir.push(lang);
+ }
+ dir = dir.join('/');
+
+ path.exists(dir, function(exists) {
+ if (!exists) {
+ fs.mkdirSync(dir, '777');
+ }
+ that.render(lang, that.options.template, dir + '/index.html');
});
}
});
-new Garden({dir: 'doc'}).render('garden.jade', 'site/index.html');
+new Garden({dir: 'doc', base: 'en', template: 'garden.jade', out: 'site'});
View
22 site/de/index.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html><html lang="en"><head><title>JavaScript Garden</title><meta charset="utf-8"><meta name="description" content="Ein Guide zu JavaScript Ecken und Kanten."><link rel="stylesheet" href="../style/garden.css" media="all"><link rel="stylesheet" href="../style/print.css" media="print"><!--[if lt IE 9]>
+<script src="/javascript/html5.js"></script>
+<![endif]-->
+</head><body><!-- Navigation--><nav><div><ul><li><a href="/" title="JavaScript Garden in English">en</a></li><li class="active"><a href="/de" title="JavaScript Garden auf Deutsch">de</a></li></ul></div><ul><li class="nav_intro"><h1><a href="#intro">Einführung</a></h1><ul><li><a href="#intro.intro">Overview</a></li><li><a href="#intro.authors">The Authors</a></li><li><a href="#intro.contributors">Contributors</a></li><li><a href="#intro.license">License</a></li></ul></li></ul></nav><!-- Sections--><section id="intro"><!-- Introduction--><header id="intro.intro"><h1>Einführung</h1><div><p>Übersetzen.</p></div></header><!-- Articles--><article id="intro.authors"><h2>The Authors</h2><div><p>This guide is the work of two lovely Stack Overflow users, <a href="http://stackoverflow.com/users/313758/yi-jiang">Ivo Wetzel</a>
+(Writing) and <a href="http://stackoverflow.com/users/170224/ivo-wetzel">Zhang Yi Jiang</a> (Design).</p>
+
+<p>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 <a href="mailto:ivo.wetzel@googlemail.com">e-mail</a> for further details.</p></div></article><article id="intro.contributors"><h2>Contributors</h2><div><ul>
+<li><a href="https://github.com/caio">Caio Romão</a> (Spelling corrections)</li>
+<li><a href="https://github.com/blixt">Andreas Blixt</a> (Language corrections)</li>
+</ul></div></article><article id="intro.license"><h2>License</h2><div><p>JavaScript Garden is published under the <a href="https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE">MIT license</a> and hosted on
+<a href="https://github.com/BonsaiDen/JavaScript-Garden">GitHub</a>. If you find errors or typos please <a href="https://github.com/BonsaiDen/JavaScript-Garden/issues">file an issue</a> or a pull
+request on the repository. You can also find us in the <a href="http://chat.stackoverflow.com/rooms/17/javascript">JavaScript room</a> on
+Stack Overflow chat. </p></div></article></section><!-- Footer--><footer><p>Copyright &copy; 2011. Built with
+<a href="http://nodejs.org/">Node.js
+
+</a>using a
+<a href="https://github.com/visionmedia/jade/">jade
+
+</a>template.
+</p></footer><script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script><script src="javascript/prettify.js"></script><script src="javascript/plugin.js"></script><script src="javascript/garden.js"></script></body></html>
View
BIN  site/image/sidebar-icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
594 site/index.html
@@ -1,4 +1,7 @@
-<!DOCTYPE html><html lang="en"><head><title>JavaScript Garden</title><meta charset="utf-8"><meta name="description" content="A Guide to JavaScript's Quirks and Flaws."><link rel="stylesheet" href="style/garden.css" media="all"><link rel="stylesheet" href="style/print.css" media="print"></head><body><!-- Navigation--><nav><ul><li><h1><a href="#intro">Intro</a></h1><ul><li><a href="#intro.intro">Overview</a></li><li><a href="#intro.authors">The authors</a></li><li><a href="#intro.contributors">Contributors</a></li><li><a href="#intro.license">License</a></li></ul></li><li><h1><a href="#object">Objects</a></h1><ul><li><a href="#object.intro">Overview</a></li><li><a href="#object.general">Object usage and properties</a></li><li><a href="#object.prototype">The prototype</a></li><li><a href="#object.hasownproperty"><code>hasOwnProperty</code></a></li><li><a href="#object.forinloop">The <code>for in</code> loop</a></li></ul></li><li><h1><a href="#function">Functions</a></h1><ul><li><a href="#function.intro">Overview</a></li><li><a href="#function.general">Function declarations and expressions</a></li><li><a href="#function.this">How <code>this</code> works</a></li><li><a href="#function.closures">Closures and references</a></li><li><a href="#function.arguments">The <code>arguments</code> object</a></li><li><a href="#function.constructors">Constructors</a></li><li><a href="#function.scopes">Scopes and namespaces</a></li></ul></li><li><h1><a href="#array">Arrays</a></h1><ul><li><a href="#array.intro">Overview</a></li><li><a href="#array.general">Array iteration and properties</a></li><li><a href="#array.constructor">The <code>Array</code> constructor</a></li></ul></li><li><h1><a href="#types">Types</a></h1><ul><li><a href="#types.intro">Overview</a></li><li><a href="#types.equality">Equality and comparisons</a></li><li><a href="#types.typeof">The <code>typeof</code> operator</a></li><li><a href="#types.instanceof">The <code>instanceof</code> operator</a></li><li><a href="#types.casting">Type casting</a></li></ul></li><li><h1><a href="#core">Core</a></h1><ul><li><a href="#core.intro">Overview</a></li><li><a href="#core.eval">The evil <code>eval</code></a></li><li><a href="#core.undefined"><code>undefined</code> and <code>null</code></a></li><li><a href="#core.semicolon">Automatic semicolon insertion</a></li></ul></li><li><h1><a href="#other">Other</a></h1><ul><li><a href="#other.intro">Overview</a></li><li><a href="#other.timeouts"><code>setTimeout</code> and <code>setInterv