Skip to content
Browse files

Cleaned up Chinese translation

  • Loading branch information...
1 parent 0f0ffb2 commit e387a6a1f63063012071a23c486c477b8080bc46 @ZhangYiJiang ZhangYiJiang committed Mar 24, 2011
View
49 README.md
@@ -1,36 +1,33 @@
-JavaScript 秘密花园
+JavaScript Garden
=================
-**JavaScript 秘密花园**是一个不断更新的文档,主要关心 JavaScript 一些古怪用法。
-对于如何避免常见的错误,难以发现的问题,以及性能问题和不好的实践给出建议,
-初学者可以籍此深入了解 JavaScript 的语言特性。
+**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 秘密花园**不是**用来教你 JavaScript。为了更好的理解这篇文章的内容,
-你需要事先学习 JavaScript 的基础知识。在 Mozilla 开发者网络中有一系列非常棒的 JavaScript 学习[向导][1]。
+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.
-### 关于作者
+### The authors
-这篇文章的作者是两位 Stack Overflow 的用户, [Ivo Wetzel][6] (写作) 和 [Zhang Yi Jiang][5] (设计)。
+This guide is the work of two lovely Stack Overflow users, [Ivo Wetzel][6]
+(Writing) and [Zhang Yi Jiang][5] (Design).
+### Contributors
-### 贡献者
+ - [Caio Romão][8] (Spelling corrections)
+ - [Andreas Blixt][9] (Language corrections)
- - [Caio Romão][8] (拼写检查)
- - [Andreas Blixt][9] (语言修正)
-
-### 中文翻译
-
- - [三生石上][29]
-
-此中文翻译由[三生石上][29]独立完成,[博客园][30]首发,转载请注明出处。
-
-
-### 许可
-
-JavaScript 秘密花园在 [MIT license][2] 许可协议下发布,并存放在开源社区 [GitHub][4]。
-如果你发现错误或者打字错误,请 [file an issue][3] 或者 pull request。
-你也可以在 Stack Overflow 的聊天室 [JavaScript room][10] 找到我们。
+### License
+JavaScript Garden is published under the [MIT license][2] and hosted on
+[GitHub][4]. 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][10] on
+Stack Overflow chat.
[1]: https://developer.mozilla.org/en/JavaScript/Guide
[2]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE
@@ -41,7 +38,3 @@ JavaScript 秘密花园在 [MIT license][2] 许可协议下发布,并存放在
[8]: https://github.com/caio
[9]: https://github.com/blixt
[10]: http://chat.stackoverflow.com/rooms/17/javascript
-
-[29]: http://sanshi.me/
-[30]: http://cnblogs.com/sanshi/
-
View
16 doc/zh/array/constructor.md
@@ -1,4 +1,4 @@
-## `Array` 构造函数
+##`Array` 构造函数
由于 `Array` 的构造函数在如何处理参数时有点模棱两可,因此总是推荐使用数组的字面语法 - `[]` - 来创建数组。
@@ -8,18 +8,17 @@
[3]; // 结果: [3]
new Array(3); // 结果: []
new Array('3') // 结果: ['3']
-
-译者注:这里的模棱两可指的是数组的[两种构造函数语法][1]
-var arr1 = new Array(arrayLength);
-var arr2 = new Array(element0, element1, ..., elementN);
// 译者注:因此下面的代码将会使人很迷惑
new Array(3, 4, 5); // 结果: [3, 4, 5]
new Array(3) // 结果: [],此数组长度为 3
+
+> **译者注:**这里的模棱两可指的是数组的[两种构造函数语法][1]
由于只有一个参数传递到构造函数中(译者注:指的是 `new Array(3);` 这种调用方式),并且这个参数是数字,构造函数会返回一个 `length` 属性被设置为此参数的空数组。
需要特别注意的是,此时只有 `length` 属性被设置,真正的数组并没有生成。
-译者注:在 Firebug 中,你会看到 [undefined, undefined, undefined],这其实是不对的。在上一节有详细的分析。
+
+> **译者注:**在 Firebug 中,你会看到 `[undefined, undefined, undefined]`,这其实是不对的。在上一节有详细的分析。
var arr = new Array(3);
arr[1]; // undefined
@@ -28,9 +27,10 @@ var arr2 = new Array(element0, element1, ..., elementN);
这种优先于设置数组长度属性的做法只在少数几种情况下有用,比如需要循环字符串,可以避免 `for` 循环的麻烦。
new Array(count + 1).join(stringToRepeat);
- // 译者注:new Array(3).join('#') 将会返回 "##"
-### 结论(In conclusion)
+> **译者注:** `new Array(3).join('#')` 将会返回 `##`
+
+###结论
应该尽量避免使用数组构造函数创建新数组。推荐使用数组的字面语法。它们更加短小和简洁,因此增加了代码的可读性。
View
26 doc/zh/array/general.md
@@ -1,4 +1,4 @@
-## 数组遍历与属性
+##数组遍历与属性
虽然在 JavaScript 中数组是是对象,但是没有好的理由去使用 [`for in` 循环](#object.forinloop) 遍历数组。
相反,有一些好的理由**不去**使用 `for in` 遍历数组。
@@ -9,7 +9,7 @@
由于 `for in` 循环会枚举原型链上的所有属性,唯一过滤这些属性的方式是使用 [`hasOwnProperty`](#object.hasownproperty) 函数,
因此会比普通的 `for` 循环慢上好多倍。
-### 遍历(Iteration)
+###遍历
为了达到遍历数组的最佳性能,推荐使用经典的 `for` 循环。
@@ -25,8 +25,7 @@
实际上,不使用缓存数组长度的方式比缓存版本要慢很多。
-
-### `length` 属性(The `length` property)
+###`length` 属性
`length` 属性的 *getter* 方式会简单的返回数组的长度,而 *setter* 方式会**截断**数组。
@@ -37,20 +36,19 @@
foo.length = 6;
foo; // [1, 2, 3]
-译者注:
-在 Firebug 中查看此时 foo 的值是: [1, 2, 3, undefined, undefined, undefined]
-但是这个结果并不准确,如果你在 Chrome 的控制台查看 foo 的结果,你会发现是这样的: [1, 2, 3]
-因为在 JavaScript 中 undefined 是一个变量,注意是变量不是关键字,因此上面两个结果的意义是完全不相同的。
-
- // 译者注:为了验证,我们来执行下面代码,看序号 5 是否存在于 foo 中。
- 5 in foo; // 不管在 Firebug 或者 Chrome 都返回 false
- foo[5] = undefined;
- 5 in foo; // 不管在 Firebug 或者 Chrome 都返回 true
+**译者注:**
+在 Firebug 中查看此时 `foo` 的值是: `[1, 2, 3, undefined, undefined, undefined]`
+但是这个结果并不准确,如果你在 Chrome 的控制台查看 `foo` 的结果,你会发现是这样的: `[1, 2, 3]`
+因为在 JavaScript 中 `undefined` 是一个变量,注意是变量不是关键字,因此上面两个结果的意义是完全不相同的。
+ // 译者注:为了验证,我们来执行下面代码,看序号 5 是否存在于 foo 中。
+ 5 in foo; // 不管在 Firebug 或者 Chrome 都返回 false
+ foo[5] = undefined;
+ 5 in foo; // 不管在 Firebug 或者 Chrome 都返回 true
`length` 设置一个更小的值会截断数组,但是增大 `length` 属性值不会对数组产生影响。
-### 结论(In conclusion)
+###结论
为了更好的性能,推荐使用普通的 `for` 循环并缓存数组的 `length` 属性。
使用 `for in` 遍历数组被认为是不好的代码习惯并倾向于产生错误和导致性能问题。
View
13 doc/zh/core/eval.md
@@ -1,4 +1,4 @@
-## 为什么不要使用 `eval`
+##为什么不要使用 `eval`
`eval` 函数会在当前作用域中执行一段 JavaScript 代码字符串。
@@ -23,7 +23,7 @@
test(); // 2
foo; // 3
-[译者注][30]:上面的代码等价于在全局作用域中调用 `eval`,和下面两种写法效果一样:
+**[译者注][30]:**上面的代码等价于在全局作用域中调用 `eval`,和下面两种写法效果一样:
// 写法一:直接调用全局作用域下的 foo 变量
var foo = 1;
@@ -35,7 +35,7 @@
test(); // 2
foo; // 3
- // 写法二:使用 call 函数修改 `eval` 执行的上下文为全局作用域
+ // 写法二:使用 call 函数修改 eval 执行的上下文为全局作用域
var foo = 1;
function test() {
var foo = 2;
@@ -47,22 +47,21 @@
**任何情况下**我们都应该避免使用 `eval` 函数。99.9% 使用 `eval` 的场景都有**不使用** `eval` 的解决方案。
-### 伪装的 `eval``eval` in disguise)
+###伪装的 `eval`
[定时函数](#other.timeouts) `setTimeout``setInterval` 都可以接受字符串作为它们的第一个参数。
这个字符串**总是**在全局作用域中执行,因此 `eval` 在这种情况下没有被直接调用。
-### 安全问题(Security issues)
+###安全问题
`eval` 也存在安全问题,因为它会执行**任意**传给它的代码,
在代码字符串未知或者是来自一个不信任的源时,绝对不要使用 `eval` 函数。
-### 结论(In conclusion)
+###结论
绝对不要使用 `eval`,任何使用它的代码都会在它的工作方式,性能和安全性方面受到质疑。
如果一些情况必须使用到 `eval` 才能正常工作,首先它的设计会受到质疑,这**不应该**是首选的解决方案,
一个更好的不使用 `eval` 的解决方案应该得到充分考虑并优先采用。
-
[30]: http://cnblogs.com/sanshi/
View
23 doc/zh/core/semicolon.md
@@ -1,4 +1,4 @@
-## 自动分号插入
+##自动分号插入
尽管 JavaScript 有 C 的代码风格,但是它**不**强制要求在代码中使用分号,实际上可以省略它们。
@@ -17,12 +17,10 @@ JavaScript 不是一个没有分号的语言,恰恰相反上它需要分号来
自动的分号插入被认为是 JavaScript 语言**最大**的设计缺陷之一,因为它*能*改变代码的行为。
-
-### 工作原理(How it works)
+### 工作原理
下面的代码没有分号,因此解析器需要自己判断需要在哪些地方插入分号。
-
(function(window, undefined) {
function test(options) {
log('testing!')
@@ -47,15 +45,14 @@ JavaScript 不是一个没有分号的语言,恰恰相反上它需要分号来
(function(window) {
window.someLibrary = {}
-
})(window)
下面是解析器"猜测"的结果。
(function(window, undefined) {
function test(options) {
- // Not inserted, lines got merged
+ // 没有插入分号,两行被合并为一行
log('testing!')(options.list || []).forEach(function(i) {
}); // <- 插入分号
@@ -67,27 +64,22 @@ JavaScript 不是一个没有分号的语言,恰恰相反上它需要分号来
return; // <- 插入分号, 改变了 return 表达式的行为
{ // 作为一个代码段处理
-
- // a label and a single expression statement
foo: function() {}
}; // <- 插入分号
}
window.test = test; // <- 插入分号
- // The lines got merged again
+ // 两行又被合并了
})(window)(function(window) {
window.someLibrary = {}; // <- 插入分号
-
})(window); //<- 插入分号
-> **注意:** JavaScript 不能正确的处理 return 表达式紧跟换行符的情况,
+> **注意:** JavaScript 不能正确的处理 `return` 表达式紧跟换行符的情况,
> 虽然这不能算是自动分号插入的错误,但这确实是一种不希望的副作用。
-
解析器显著改变了上面代码的行为,在另外一些情况下也会做出**错误的处理**
-
-### 前置括号(Leading parenthesis)
+###前置括号
在前置括号的情况下,解析器**不会**自动插入分号。
@@ -100,8 +92,7 @@ JavaScript 不是一个没有分号的语言,恰恰相反上它需要分号来
`log` 函数的执行结果**极大**可能**不是**函数;这种情况下就会出现 `TypeError` 的错误,详细错误信息可能是 `undefined is not a function`
-
-### 结论(In conclusion)
+###结论
建议**绝对**不要省略分号,同时也提倡将花括号和相应的表达式放在一行,
对于只有一行代码的 `if` 或者 `else` 表达式,也不应该省略花括号。
View
17 doc/zh/core/undefined.md
@@ -1,9 +1,8 @@
-## `undefined``null`
+##`undefined``null`
-JavaScript 有两个表示 `空` 的值,其中比较有用的是 `undefined`
+JavaScript 有两个表示‘空’的值,其中比较有用的是 `undefined`
-
-### `undefined`的值(The value `undefined`
+###`undefined` 的值
`undefined` 是一个值为 `undefined` 的类型。
@@ -22,8 +21,7 @@ JavaScript 有两个表示 `空` 的值,其中比较有用的是 `undefined`
- 函数参数没有被显式的传递值。
- 任何被设置为 `undefined` 值的变量。
-
-### 处理 `undefined` 值的改变(Handling changes to the value of `undefined`
+###处理 `undefined` 值的改变
由于全局变量 `undefined` 只是保存了 `undefined` 类型实际*值*的副本,
因此对它赋新值**不会**改变类型 `undefined` 的值。
@@ -50,11 +48,10 @@ JavaScript 有两个表示 `空` 的值,其中比较有用的是 `undefined`
这里唯一的区别是,在压缩后并且函数内没有其它需要使用 `var` 声明变量的情况下,这个版本的代码会多出 4 个字节的代码。
-[译者注][30]:这里有点绕口,其实很简单。
-如果此函数内没有其它需要声明的变量,那么 `var ` 总共 4 个字符(包含一个空白字符)就是专门为 undefined 变量准备的,相比上个例子多出了 4 个字节。
-
+> **[译者注][30]:**这里有点绕口,其实很简单。如果此函数内没有其它需要声明的变量,那么 `var` 总共 4 个字符(包含一个空白字符)
+就是专门为 `undefined` 变量准备的,相比上个例子多出了 4 个字节。
-### 使用 `null`(Uses of `null`
+###`null` 的用处
JavaScript 中的 `undefined` 的使用场景类似于其它语言中的 *null*,实际上 JavaScript 中的 `null` 是另外一种数据类型。
View
21 doc/zh/function/arguments.md
@@ -1,4 +1,4 @@
-## `arguments` 对象
+##`arguments` 对象
JavaScript 中每个函数内都能访问一个特别变量 `arguments`。这个变量维护着所有传递到这个函数中的参数列表。
@@ -12,15 +12,15 @@ JavaScript 中每个函数内都能访问一个特别变量 `arguments`。这个
因此,无法对 `arguments` 变量使用标准的数组方法,比如 `push`, `pop` 或者 `slice`
虽然使用 `for` 循环遍历也是可以的,但是为了更好的使用数组方法,最好把它转化为一个真正的数组。
-### 转化为数组(Converting to an array)
+###转化为数组
下面的代码将会创建一个新的数组,包含所有 `arguments` 对象中的元素。
Array.prototype.slice.call(arguments);
这个转化比较**慢**,在性能不好的代码中**不推荐**这种做法。
-### 传递参数(Passing arguments)
+###传递参数
下面将参数从一个函数传递到另一个函数,是推荐的做法。
@@ -48,15 +48,15 @@ JavaScript 中每个函数内都能访问一个特别变量 `arguments`。这个
};
-[译者注][30]:上面的 `Foo.method` 函数和下面代码的效果是一样的:
+**[译者注][30]**:上面的 `Foo.method` 函数和下面代码的效果是一样的:
Foo.method = function() {
var args = Array.prototype.slice.call(arguments);
Foo.prototype.method.apply(args[0], args.slice(1));
};
-### 自动更新(Modification "magic")
+###自动更新
`arguments` 对象为其内部属性以及函数形式参数创建 *getter**setter* 方法。
@@ -75,7 +75,7 @@ JavaScript 中每个函数内都能访问一个特别变量 `arguments`。这个
}
foo(1, 2, 3);
-### 性能真相(Performance myths and truths)
+### 性能真相
`arguments` 对象总会被创建,除了两个特殊情况 - 作为局部变量声明和作为形式参数。
而不管它是否有被使用。
@@ -85,12 +85,10 @@ JavaScript 中每个函数内都能访问一个特别变量 `arguments`。这个
> **ES5 提示:** 这些 *getters**setters* 在严格模式下(strict mode)不会被创建。
-
-[译者注][30]:在 [MDC][2] 中对 `strict mode` 模式下 `arguments` 的描述有助于我们的理解,请看下面代码:
+**[译者注][30]:**在 [MDC][2] 中对 `strict mode` 模式下 `arguments` 的描述有助于我们的理解,请看下面代码:
// 阐述在 ES5 的严格模式下 `arguments` 的特性
- function f(a)
- {
+ function f(a) {
"use strict";
a = 42;
return [a, arguments[0]];
@@ -112,13 +110,12 @@ JavaScript 中每个函数内都能访问一个特别变量 `arguments`。这个
}
}
-上面代码中,`foo` 不再是一个单纯的内联函数 [inlining][1]([译者注][30]:这里指的是解析器可以做内联处理),
+上面代码中,`foo` 不再是一个单纯的内联函数 [inlining][1](**[译者注][30]**:这里指的是解析器可以做内联处理),
因为它需要知道它自己和它的调用者。
这不仅抵消了内联函数带来的性能提升,而且破坏了封装,因此现在函数可能要依赖于特定的上下文。
因此**强烈**建议大家**不要**使用 `arguments.callee` 和它的属性。
-
> **ES5 提示:** 在严格模式下,`arguments.callee` 会报错 `TypeError`,因为它已经被废除了。
[1]: http://en.wikipedia.org/wiki/Inlining
View
17 doc/zh/function/closures.md
@@ -1,9 +1,9 @@
-## 闭包和引用
+##闭包和引用
闭包是 JavaScript 一个非常重要的特性,这意味着当前作用域**总是**能够访问外部作用域中的变量。
因为 [函数](#scopes) 是 JavaScript 中唯一拥有自身作用域的结构,因此闭包的创建依赖于函数。
-### 模拟私有变量(Emulating private variables)
+###模拟私有变量
function Counter(start) {
var count = start;
@@ -25,7 +25,7 @@
这里,`Counter` 函数返回两个闭包,函数 `increment` 和函数 `get`。 这两个函数都维持着
对外部作用域 `Counter` 的引用,因此总可以访问此作用域内定义的变量 `count`.
-### 为什么不可以在外部访问私有变量(Why private variables work)
+###为什么不可以在外部访问私有变量
因为 JavaScript 中不可以对作用域进行引用或赋值,因此没有办法在外部访问 `count` 变量。
唯一的途径就是通过那两个闭包。
@@ -38,10 +38,9 @@
上面的代码**不会**改变定义在 `Counter` 作用域中的 `count` 变量的值,因为 `foo.hack` 没有
定义在那个**作用域**内。它将会创建或者覆盖*全局*变量 `count`
-### 循环中的闭包(Closures inside loops)
+###循环中的闭包
-一个常见的错误出现在循环中使用闭包,假设我们需要在每次循环中调用循环序号(as if they were
-copying the value of the loops index variable.)。
+一个常见的错误出现在循环中使用闭包,假设我们需要在每次循环中调用循环序号
for(var i = 0; i < 10; i++) {
setTimeout(function() {
@@ -51,13 +50,13 @@ copying the value of the loops index variable.)。
上面的代码不会输出数字 `0``9`,而是会输出数字 `10` 十次。
-当 `console.log` 被调用的时候,*匿名*函数保持对外部变量 `i` 的引用,此时 `for 循环`已经结束`i` 的值被修改成了 `10`.
+当 `console.log` 被调用的时候,*匿名*函数保持对外部变量 `i` 的引用,此时 `for`循环已经结束`i` 的值被修改成了 `10`.
为了得到想要的结果,需要在每次循环中创建变量 `i`**拷贝**
-### 避免引用错误(Avoiding the reference problem)
+###避免引用错误
-为了正确的获得循环序号,最好使用 [匿名包裹器](#scopes)([译者注][30]:其实就是我们通常说的自执行匿名函数)。
+为了正确的获得循环序号,最好使用 [匿名包裹器](#scopes)(**[译者注][30]:**其实就是我们通常说的自执行匿名函数)。
for(var i = 0; i < 10; i++) {
(function(e) {
View
22 doc/zh/function/constructors.md
@@ -1,4 +1,4 @@
-## 构造函数
+##构造函数
JavaScript 中的构造函数和其它语言中的构造函数是不同的。
通过 `new` 关键字方式调用的函数都被认为是构造函数。
@@ -37,16 +37,17 @@ JavaScript 中的构造函数和其它语言中的构造函数是不同的。
new Test(); // 返回的对象
-[译者注][30]:new Bar() 返回的是新创建的对象,而不是数字的字面值 2。
-因此 new Bar().constructor === Bar,但是如果返回的是数字对象,结果就不同了,如下所示
+**[译者注][30]:**`new Bar()` 返回的是新创建的对象,而不是数字的字面值 2。
+因此 `new Bar().constructor === Bar`,但是如果返回的是数字对象,结果就不同了,如下所示
function Bar() {
return new Number(2);
}
new Bar().constructor === Number
-[译者注][30]:这里得到的(new Test())是函数返回的对象,而不是通过 new 关键字新创建的对象,因此:
+**[译者注][30]:**这里得到的 `new Test()`是函数返回的对象,而不是通过`new`关键字新创建的对象,因此:
+
(new Test()).value === undefined
(new Test()).foo === 1
@@ -61,7 +62,7 @@ JavaScript 中的构造函数和其它语言中的构造函数是不同的。
虽然上例在有些情况下也能正常运行,但是由于 JavaScript 中 [`this`](#function.this) 的工作原理,
这里的 `this` 指向*全局对象*
-### 工厂模式(Factories)
+### 工厂模式
为了不使用 `new` 关键字,构造函数必须显式的返回一个值。
@@ -83,13 +84,12 @@ JavaScript 中的构造函数和其它语言中的构造函数是不同的。
上面两种对 `Bar` 函数的调用返回的值完全相同,一个新创建的拥有 `method` 属性的对象被返回,
其实这里创建了一个[闭包](#function.closures)。
-
-还需要注意,`new Bar()`**不会**改变返回对象的原型([译者注][30]:也就是返回对象的原型不会指向 Bar.prototype)。
+还需要注意, `new Bar()`**不会**改变返回对象的原型(**[译者注][30]:**也就是返回对象的原型不会指向 `Bar.prototype`)。
因为构造函数的原型会被指向到刚刚创建的新对象,而这里的 `Bar` 没有把这个新对象返回([译者注][30]:而是返回了一个包含 `method` 属性的自定义对象)。
在上面的例子中,使用或者不使用 `new` 关键字没有功能性的区别。
-[译者注][30]:上面两种方式创建的对象不能访问 Bar 原型链上的属性,如下所示:
+**[译者注][30]:**上面两种方式创建的对象不能访问 `Bar` 原型链上的属性,如下所示:
var bar1 = new Bar();
typeof(bar1.method); // "function"
@@ -99,8 +99,7 @@ JavaScript 中的构造函数和其它语言中的构造函数是不同的。
typeof(bar2.method); // "function"
typeof(bar2.foo); // "undefined"
-
-### 通过工厂模式创建新对象(Creating new objects via factories)
+###通过工厂模式创建新对象
我们常听到的一条忠告是**不要**使用 `new` 关键字来调用函数,因为如果忘记使用它就会导致错误。
@@ -129,10 +128,9 @@ JavaScript 中的构造函数和其它语言中的构造函数是不同的。
2. 为了实现继承,工厂方法需要从另外一个对象拷贝所有属性,或者把一个对象作为新创建对象的原型。
3. 放弃原型链仅仅是因为防止遗漏 `new` 带来的问题,这似乎和语言本身的思想相违背。
-### 总结(In conclusion)
+###总结
虽然遗漏 `new` 关键字可能会导致问题,但这并**不是**放弃使用原型链的借口。
最终使用哪种方式取决于应用程序的需求,选择一种代码书写风格并**坚持**下去才是最重要的。
-
[30]: http://cnblogs.com/sanshi/
View
9 doc/zh/function/general.md
@@ -1,9 +1,9 @@
-## 函数声明与表达式
+##函数声明与表达式
函数是JavaScript中的一等对象,这意味着可以把函数像其它值一样传递。
一个常见的用法是把*匿名函数*作为回调函数传递对异步函数中。
-### 函数声明(The `function` declaration)
+###函数声明
function foo() {}
@@ -13,7 +13,7 @@
foo(); // 正常运行,因为foo在代码运行前已经被创建
function foo() {}
-### 函数赋值表达式(The `function` expression)
+### 函数赋值表达式
var foo = function() {};
@@ -27,7 +27,7 @@
但是由于赋值语句只在运行时执行,因此在相应代码执行之前, `foo` 的值缺省为 [undefined](#undefined)。
-### 命名函数的赋值表达式(Named function expression)
+###命名函数的赋值表达式
另外一个特殊的情况是将命名函数赋值给一个变量。
@@ -40,5 +40,4 @@
然而在 `bar` 内部依然可见。这是由于 JavaScript 的 [命名处理](#scopes) 所致,
函数名在函数内*总是*可见的。
-
[30]: http://cnblogs.com/sanshi/
View
27 doc/zh/function/scopes.md
@@ -1,4 +1,4 @@
-## 作用域与命名空间
+##作用域与命名空间
尽管 JavaScript 支持一对花括号创建的代码段,但是并不支持块级作用域;
而仅仅支持 *函数作用域*
@@ -13,7 +13,7 @@
> **注意:** 如果不是在赋值语句中,而是在 return 表达式或者函数参数中,`{...}` 将会作为代码段解析,
> 而不是作为对象的字面语法解析。如果考虑到 [自动分号插入](#semicolon),这可能会导致一些不易察觉的错误。
-[译者注][30]:如果 return 对象的左括号和 return 不在一行上就会出错。
+**[译者注][30]:**如果 `return` 对象的左括号和 `return` 不在一行上就会出错。
// 译者注:下面输出 undefined
function add(a, b) {
@@ -27,12 +27,12 @@ JavaScript 中没有显式的命名空间定义,这就意味着所有对象都
每次引用一个变量,JavaScript 会向上遍历整个作用域直到找到这个变量为止。
如果到达全局作用域但是这个变量仍未找到,则会抛出 `ReferenceError` 异常。
-### 隐式的全局变量(The bane of global variables)
+###隐式的全局变量
- // script A
+ // 脚本 A
foo = '42';
- // script B
+ // 脚本 B
var foo = '42'
上面两段脚本效果**不同**。脚本 A 在*全局*作用域内定义了变量 `foo`,而脚本 B 在*当前*作用域内定义变量 `foo`
@@ -68,7 +68,7 @@ JavaScript 中没有显式的命名空间定义,这就意味着所有对象都
在第二个 `for` 循环中使用 `var` 声明变量可以避免这种错误。
声明变量时**绝对不要**遗漏 `var` 关键字,除非这就是*期望*的影响外部作用域的行为。
-### 局部变量(Local variables)
+###局部变量
JavaScript 中局部变量只可能通过两种方式声明,一个是作为[函数](#functions)参数,另一个是通过 `var` 关键字声明。
@@ -136,7 +136,7 @@ JavaScript 会**提升**变量声明。这意味着 `var` 表达式和 `function
没有块级作用域不仅导致 `var` 表达式被从循环内移到外部,而且使一些 `if` 表达式更难看懂。
-在原来代码中,`if` 表达式看起来修改了*全部变量* `goo`,实际上在提升规则(hoisting)被应用后,却是在修改*局部变量*。
+在原来代码中,`if` 表达式看起来修改了*全部变量* `goo`,实际上在提升规则被应用后,却是在修改*局部变量*。
如果没有提升规则(hoisting)的知识,下面的代码看起来会抛出异常 `ReferenceError`。
@@ -157,7 +157,7 @@ JavaScript 会**提升**变量声明。这意味着 `var` 表达式和 `function
}
-[译者注][30]:在 Nettuts+ 网站有一篇介绍 hoisting 的[文章][1],其中的代码很有启发性。
+**[译者注][30]:**在 Nettuts+ 网站有一篇介绍 hoisting 的[文章][1],其中的代码很有启发性。
// 译者注:来自 Nettuts+ 的一段代码,生动的阐述了 JavaScript 中变量声明提升规则
var myvar = 'my value';
@@ -168,7 +168,7 @@ JavaScript 会**提升**变量声明。这意味着 `var` 表达式和 `function
})();
-### 名称解析顺序(Name resolution order)
+###名称解析顺序
JavaScript 中的所有作用域,包括*全局作用域*,都有一个特别的名称 [`this`](#this) 指向当前对象。
@@ -183,7 +183,7 @@ JavaScript 中的所有作用域,包括*全局作用域*,都有一个特别
> **注意:** 自定义 `arguments` 参数将会阻止原生的 `arguments` 对象的创建。
-### 命名空间(Namespaces)
+###命名空间
只有一个全局作用域导致的常见错误是命名冲突。在 JavaScript中,这可以通过 *匿名包装器* 轻松解决。
@@ -196,7 +196,7 @@ JavaScript 中的所有作用域,包括*全局作用域*,都有一个特别
})(); // 立即执行此匿名函数
-匿名函数被认为是 [表达式](#functions);因此为了可调用性,它们首先会被执行(evaluated)
+匿名函数被认为是 [表达式](#functions);因此为了可调用性,它们首先会被执行。
( // 小括号内的函数首先被执行
function() {}
@@ -209,13 +209,12 @@ JavaScript 中的所有作用域,包括*全局作用域*,都有一个特别
+function(){}();
(function(){}());
-### 结论(In conclusion)
+###结论
-推荐使用*匿名包装器*([译者注][30]:也就是自执行的匿名函数)来创建命名空间。这样不仅可以防止命名冲突,
+推荐使用*匿名包装器***[译者注][30]:**也就是自执行的匿名函数)来创建命名空间。这样不仅可以防止命名冲突,
而且有利于程序的模块化。
另外,使用全局变量被认为是**不好的习惯**。这样的代码倾向于产生错误和带来高的维护成本。
-
[1]: http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-javascript-hoisting-explained/
[30]: http://cnblogs.com/sanshi/
View
28 doc/zh/function/this.md
@@ -1,18 +1,17 @@
-## this 的工作原理
+##`this` 的工作原理
JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。
**五**种不同的情况下 ,`this` 指向的各不相同。
-### 全局范围内(The global scope)
+###全局范围内
this;
当在全部范围内使用 `this`,它将会指向*全局*对象。
-[译者注][30]:浏览器中运行的JavaScript脚本,这个全局对象是 window。
+> **[译者注][30]:**浏览器中运行的 JavaScript 脚本,这个全局对象是 `window`
-
-### 函数调用(Calling a function)
+###函数调用
foo();
@@ -22,20 +21,20 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。
> 这种情况下 `this` 将会是 `undefined`
> [译者注][30]:ES5指的是ECMAScript 5,是 2009-12 发布的最新的 JavaScript 版本。
-### 方法调用(Calling a method)
+###方法调用
test.foo();
这个例子中,`this` 指向 `test` 对象。
-### 调用构造函数(Calling a constructor)
+###调用构造函数
new foo();
如果函数倾向于和 `new` 关键词一块使用,则我们称这个函数是 [构造函数](#constructors)。
在函数内部,`this` 指向*新创建*的对象。
-### 显式的设置 `this`(Explicit setting of `this`
+###显式的设置 `this`
function foo(a, b, c) {}
@@ -50,16 +49,16 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。
> **注意:** 在对象的字面声明语法中,`this` **不能**用来指向对象本身。
> 因此 `var obj = {me: this}` 中的 `me` 不会指向 `obj`,因为 `this` 只可能出现在上述的五种情况中。
-> [译者注][30]:这个例子中,如果是在浏览器中运行,obj.me等于window对象
+> **[译者注][30]:**这个例子中,如果是在浏览器中运行,`obj.me` 等于 `window` 对象
-### 常见误解(Common pitfalls)
+###常见误解
-尽管大部分的情况都说的过去,不过第一个规则([译者注][30]:这里指的应该是第二个规则,也就是直接调用函数时,`this` 指向全局对象)
+尽管大部分的情况都说的过去,不过第一个规则(**[译者注][30]:**这里指的应该是第二个规则,也就是直接调用函数时,`this` 指向全局对象)
被认为是JavaScript语言另一个错误设计的地方,因为它**从来**就没有实际的用途。
Foo.method = function() {
function test() {
- // this 将会被设置为全局对象([译者注][30]:浏览器环境中也就是 window 对象)
+ // this 将会被设置为全局对象(译者注:浏览器环境中也就是 window 对象)
}
test();
}
@@ -77,9 +76,9 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。
}
`that` 只是我们随意起的名字,不过这个名字被广泛的用来指向外部的 `this` 对象。
-在 [closures](#closures) 一节,我们可以看到 `that` 可以作为参数传递。
+在 [闭包](#closures) 一节,我们可以看到 `that` 可以作为参数传递。
-### 方法的赋值表达式(Assigning methods)
+###方法的赋值表达式
另一个看起来奇怪的地方是函数别名,也就是将一个方法**赋值**给一个变量。
@@ -100,5 +99,4 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。
`method` 被调用时,`this` 将会指向 `Bar` 的实例对象。
-
[30]: http://cnblogs.com/sanshi/
View
6 doc/zh/index.json
@@ -1,7 +1,7 @@
{
- "title": "JavaScript Garden",
- "langTitle": "JavaScript Garden in English",
- "description": "A Guide to JavaScript's Quirks and Flaws.",
+ "title": "JavaScript 秘密花园",
+ "langTitle": "JavaScript Garden 中文翻译",
+ "description": "JavaScript 语言最古怪用法的文档集合",
"sections": [
{
"title": "简介",
View
7 doc/zh/intro/authors.md
@@ -1,6 +1,7 @@
## 关于作者
-这篇文章的作者是两位 Stack Overflow 的用户, [Ivo Wetzel][1] (写作) 和 [Zhang Yi Jiang][2] (设计)。
+这篇文章的作者是两位 [Stack Overflow][1] 用户, [伊沃·韦特泽尔 Ivo Wetzel][2](写作) 和 [张易江 Zhang Yi Jiang][3](设计)。
-[1]: http://stackoverflow.com/users/170224/ivo-wetzel
-[2]: http://stackoverflow.com/users/313758/yi-jiang
+[1]: http://stackoverflow.com/
+[2]: http://stackoverflow.com/users/170224/ivo-wetzel
+[3]: http://stackoverflow.com/users/313758/yi-jiang
View
4 doc/zh/intro/contributors.md
@@ -7,10 +7,8 @@
- [三生石上][29]
此中文翻译由[三生石上][29]独立完成,[博客园][30]首发,转载请注明出处。
-
-
+
[1]: https://github.com/caio
[2]: https://github.com/blixt
-
[29]: http://sanshi.me/
[30]: http://cnblogs.com/sanshi/
View
2 doc/zh/intro/index.md
@@ -1,6 +1,6 @@
## 简介
-**JavaScript 秘密花园**是一个不断更新的文档,主要关心 JavaScript 一些古怪用法
+**JavaScript 秘密花园**是一个不断更新,主要关心 JavaScript 一些古怪用法的文档
对于如何避免常见的错误,难以发现的问题,以及性能问题和不好的实践给出建议,
初学者可以籍此深入了解 JavaScript 的语言特性。
View
7 doc/zh/intro/license.md
@@ -1,9 +1,8 @@
## 许可
-JavaScript 秘密花园在 [MIT license][1] 许可协议下发布,并存放在开源社区 [GitHub][2]。
-如果你发现错误或者打字错误,请 [file an issue][3] 或者 pull request。
-你也可以在 Stack Overflow 的聊天室 [JavaScript room][4] 找到我们。
-
+JavaScript 秘密花园在 [MIT license][1] 许可协议下发布,并存放在 [GitHub][2] 开源社区。
+如果你发现错误或者打字错误,请[新建一个任务单][3]或者发一个抓取请求。
+你也可以在 Stack Overflow 的 [JavaScript 聊天室][4] 找到我们。
[1]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE
[2]: https://github.com/BonsaiDen/JavaScript-Garden
View
10 doc/zh/object/forinloop.md
@@ -1,9 +1,9 @@
-## `for in` 循环
+##`for in` 循环
`in` 操作符一样,`for in` 循环同样在查找对象属性时遍历原型链上的所有属性。
> **注意:** `for in` 循环**不会**遍历那些 `enumerable` 设置为 `false` 的属性;比如数组的 `length` 属性。
-
+
// 修改 Object.prototype
Object.prototype.bar = 1;
@@ -17,7 +17,7 @@
> **注意:** 由于 `for in` 总是要遍历整个原型链,因此如果一个对象的继承层次太深的话会影响性能。
-### 使用 `hasOwnProperty` 过滤(Using `hasOwnProperty` for filtering)
+###使用 `hasOwnProperty` 过滤
// foo 变量是上例中的
for(var i in foo) {
@@ -32,12 +32,10 @@
一个广泛使用的类库 [Prototype][1] 就扩展了原生的 JavaScript 对象。
因此,但这个类库被包含在页面中时,不使用 `hasOwnProperty` 过滤的 `for in` 循环难免会出问题。
-
-### 最佳实践(Best practices)
+###总结
推荐**总是**使用 `hasOwnProperty`。不要对代码运行的环境做任何假设,不要假设原生对象是否已经被扩展了。
-
[1]: http://www.prototypejs.org/
[30]: http://cnblogs.com/sanshi/
View
14 doc/zh/object/general.md
@@ -1,4 +1,4 @@
-## 对象使用和属性
+##对象使用和属性
JavaScript 中所有变量都是对象,除了两个例外 [`null`](#undefined) 和 [`undefined`](#undefined)。
@@ -20,7 +20,7 @@ JavaScript 中所有变量都是对象,除了两个例外 [`null`](#undefined)
2 .toString(); // 注意点号前面的空格
(2).toString(); // 2先被计算
-### 对象作为数据类型(Objects as a data type)
+###对象作为数据类型
JavaScript 的对象可以作为[*哈希表*][1]使用,主要用来保存命名的键与值的对应关系。
@@ -32,7 +32,7 @@ JavaScript 的对象可以作为[*哈希表*][1]使用,主要用来保存命
// 一个新对象,拥有一个值为12的自定义属性'test'
var bar = {test: 12};
-### 访问属性(Accessing properties)
+### 访问属性
有两种方式来访问对象的属性,点操作符或者中括号操作符。
@@ -48,11 +48,11 @@ JavaScript 的对象可以作为[*哈希表*][1]使用,主要用来保存命
两种语法是等价的,但是中括号操作符在下面两种情况下依然有效
- 动态设置属性
- - 属性名不是一个有效的变量名([译者注][30]:比如属性名中包含空格,或者属性名是JS的关键词
+ - 属性名不是一个有效的变量名(**[译者注][30]:**比如属性名中包含空格,或者属性名是 JS 的关键词
-[译者注][30]:在 [JSLint][2] 语法检测工具中,点操作符是推荐做法。
+> **[译者注][30]:**在 [JSLint][2] 语法检测工具中,点操作符是推荐做法。
-### 删除属性(Deleting properties)
+###删除属性
删除属性的唯一方法是使用 `delete` 操作符;设置属性为 `undefined` 或者 `null` 并不能真正的删除属性,
**仅仅**是移除了属性和值的关联。
@@ -74,7 +74,7 @@ JavaScript 的对象可以作为[*哈希表*][1]使用,主要用来保存命
上面的输出结果有 `bar undefined``foo null` - 只有 `baz` 被真正的删除了,所以从输出结果中消失。
-### 属性名的语法(Notation of keys)
+###属性名的语法
var test = {
'case': 'I am a keyword so I must be notated as a string',
View
9 doc/zh/object/hasownproperty.md
@@ -1,13 +1,12 @@
-## `hasOwnProperty` 函数
+##`hasOwnProperty` 函数
为了判断一个对象是否包含*自定义*属性而*不是*[原型链](#prototype)上的属性,
我们需要使用继承自 `Object.prototype``hasOwnProperty` 方法。
-
> **注意:** 通过判断一个属性是否 `undefined`**不够**的。
> 因为一个属性可能确实存在,只不过它的值被设置为 `undefined`
-`hasOwnProperty` 是JavaScript中唯一一个处理属性但是**不需要**查找原型链的方法
+`hasOwnProperty` 是 JavaScript 中唯一一个处理属性但是**不**查找原型链的函数
// 修改Object.prototype
Object.prototype.bar = 1;
@@ -22,7 +21,7 @@
只有 `hasOwnProperty` 可以给出正确和期望的结果,这在遍历对象的属性时会很有用。
**没有**其它方法可以用来排除原型链上的属性,而不是定义在对象*自身*上的属性。
-### `hasOwnProperty` 作为属性`hasOwnProperty` as a property)
+###`hasOwnProperty` 作为属性
JavaScript **不会**保护 `hasOwnProperty` 被非法占用,因此如果一个对象碰巧存在这个属性,
就需要使用*外部*`hasOwnProperty` 函数来获取正确的结果。
@@ -39,7 +38,7 @@ JavaScript **不会**保护 `hasOwnProperty` 被非法占用,因此如果一
// 使用其它对象的 hasOwnProperty,并将其上下为设置为foo
{}.hasOwnProperty.call(foo, 'bar'); // true
-### 结论(In conclusion)
+###结论
当检查对象上某个属性是否存在时,`hasOwnProperty`**唯一**可用的方法。
同时在使用 [`for in` loop](#forinloop) 遍历对象时,推荐**总是**使用 `hasOwnProperty` 方法,
View
31 doc/zh/object/prototype.md
@@ -1,16 +1,16 @@
-## 原型
+##原型
-JavaScript 不包含传统的类继承模型,而是使用 *prototypical* 原型模型。
+JavaScript 不包含传统的类继承模型,而是使用 *prototypal* 原型模型。
虽然这经常被当作是 JavaScript 的缺点被提及,其实基于原型的继承模型比传统的类继承还要强大。
实现传统的类继承模型是很简单,但是实现 JavaScript 中的原型继承则要困难的多。
-It is for example fairly trivial to build a classic model on top of it, while the
-other way around is a far more difficult task.
+(It is for example fairly trivial to build a classic model on top of it, while the
+other way around is a far more difficult task.)
由于 JavaScript 是唯一一个被广泛使用的基于原型继承的语言,所以理解两种继承模式的差异是需要一定时间的。
第一个不同之处在于 JavaScript 使用*原型链*的继承方式。
-
+
> **注意:** 简单的使用 `Bar.prototype = Foo.prototype` 将会导致两个对象共享**相同**的原型。
> 因此,改变任意一个对象的原型都会影响到另一个对象的原型,在大多数情况下这不是希望的结果。
@@ -44,24 +44,24 @@ other way around is a far more difficult task.)
上面的例子中,`test` 对象从 `Bar.prototype` 和 `Foo.prototype` 继承下来;因此,
它能否访问 `Foo` 的原型方法 `method`。但是它不能访问 `Foo` 的实例属性 `value`,
因为这个属性在`Foo`的[构造函数](#constructor)中定义。
-But it will not have access to the property `value` of a
+(But it will not have access to the property `value` of a
`Foo` instance, since that property gets defined in the [constructor](#constructor)
-of `Foo`. But this constructor has to be called explicitly.
+of `Foo`. But this constructor has to be called explicitly.)
-[译者注][30]:我认为这个描述是错误的,test.value 是可以访问的。
-因为在设置 Bar.prototype = new Foo(); 时,`value` 也就成为 Bar.prototype 上的一个属性。
+> **[译者注][30]:**我认为这个描述是错误的,`test.value` 是可以访问的。
+因为在设置 `Bar.prototype = new Foo();` 时,`value` 也就成为 `Bar.prototype` 上的一个属性。
如果你有不同观点,可以到[我的博客][30]评论。
> **注意:** **不要**使用 `Bar.prototype = Foo`,因为这不会执行 `Foo` 的原型,而是指向函数 `Foo`
> 因此原型链将会回溯到 `Function.prototype` 而不是 `Foo.prototype`,因此 `method` 将不会在 Bar 的原型链上。
-### 属性查找(Property lookup)
+###属性查找
当查找一个对象的属性时,JavaScript 会**向上**遍历原型链,直到找到给定名称的属性为止。
到查找到达原型链的顶部 - 也就是 `Object.prototype` - 但是仍然没有找到指定的属性,就会返回 [undefined](#undefined)。
-### 原型属性(The prototype property)
+###原型属性
当原型属性用来创建原型链时,可以把**任何**类型的值赋给它(prototype)。
然而将原子类型赋给 prototype 的操作将会被忽略。
@@ -71,13 +71,13 @@ of `Foo`. But this constructor has to be called explicitly.)
而将对象赋值给 prototype,正如上面的例子所示,将会动态的创建原型链。
-### 性能(Performance)
+###性能
如果一个属性在原型链的上端,则对于查找时间将带来不利影响。特别的,试图获取一个不存在的属性将会遍历整个原型链。
并且,当使用 [for-in](#the-for-in-loop) 循环遍历对象的属性时,原型链上的**所有**属性都将被访问。
-### 扩展内置类型的原型(Extension of native prototypes)
+###扩展内置类型的原型
一个错误特性被经常使用,那就是扩展 `Object.prototype` 或者其他内置类型的原型对象。
@@ -86,10 +86,9 @@ of `Foo`. But this constructor has to be called explicitly.)
扩展内置类型的**唯一**理由是为了和新的 JavaScript 保持一致,比如 [`Array.forEach`][3]。
-[译者注][30]:这是编程领域常用的一种方式,称之为 [Backport][5],也就是将新的补丁添加到老版本中。
-
+> **[译者注][30]:**这是编程领域常用的一种方式,称之为 [Backport][5],也就是将新的补丁添加到老版本中。
-### 总结(In conclusion)
+###总结
在写复杂的 JavaScript 应用之前,充分理解原型链继承的工作方式是每个 JavaScript 程序员**必修**的功课。
要提防原型链过长带来的性能问题,并知道如何通过缩短原型链来提高性能。
View
25 doc/zh/other/timeouts.md
@@ -1,8 +1,8 @@
-### `setTimeout``setInterval`
+###`setTimeout``setInterval`
由于 JavaScript 是异步的,可以使用 `setTimeout``setInterval` 来计划执行函数。
-> **注意:** 定时处理**不是** ECMAScript 的标准,它们在 [DOM][1] 被实现。
+> **注意:** 定时处理**不是** ECMAScript 的标准,它们在 [DOM (文档对象模型)][1] 被实现。
function foo() {}
var id = setTimeout(foo, 1000); // 返回一个大于零的数字
@@ -30,8 +30,7 @@
> 这里回调函数是 `foo`**返回值**,而**不是**`foo`本身。
> 大部分情况下,这是一个潜在的错误,因为如果函数返回 `undefined``setTimeout`**不会**报错。
-
-### `setInterval` 的堆调用(Stacking calls with `setInterval`
+###`setInterval` 的堆调用
`setTimeout` 只会执行回调函数一次,不过 `setInterval` - 正如名字建议的 - 会每隔 `X` 毫秒执行函数一次。
但是却不鼓励使用这个函数。
@@ -48,7 +47,7 @@
`foo` 被阻塞的时候,`setInterval` 仍然在组织将来对回调函数的调用。
因此,当第一次 `foo` 函数调用结束时,已经有 **10** 次函数调用在等待执行。
-### 处理可能的阻塞调用(Dealing with possible blocking code)
+###处理可能的阻塞调用
最简单也是最容易控制的方案,是在回调函数内部使用 `setTimeout` 函数。
@@ -62,15 +61,15 @@
`foo` 函数现在可以控制是否继续执行还是终止执行。
-### 手工清空定时器(Manually clearing timeouts)
+###手工清空定时器
可以通过将定时时产生的 ID 标识传递给 `clearTimeout` 或者 `clearInterval` 函数来清除定时,
至于使用哪个函数取决于调用的时候使用的是 `setTimeout` 还是 `setInterval`
var id = setTimeout(foo, 1000);
clearTimeout(id);
-### 清除所有定时器(Clearing all timeouts)
+###清除所有定时器
由于没有内置的清除所有定时器的方法,可以采用一种暴力的方式来达到这一目的。
@@ -79,15 +78,14 @@
clearTimeout(i);
}
-可能还有些定时器不会在上面代码中被清除([译者注][30]:如果定时器调用时返回的 ID 值大于 1000),
+可能还有些定时器不会在上面代码中被清除(**[译者注][30]:**如果定时器调用时返回的 ID 值大于 1000),
因此我们可以事先保存所有的定时器 ID,然后一把清除。
-### 隐藏使用 `eval`(Hidden use of `eval`
+###隐藏使用 `eval`
`setTimeout``setInterval` 也接受第一个参数为字符串的情况。
这个特性**绝对**不要使用,因为它在内部使用了 `eval`
-
> **注意:** 由于定时器函数不是 ECMAScript 的标准,如何解析字符串参数在不同的 JavaScript 引擎实现中可能不同。
> 事实上,微软的 JScript 会使用 `Function` 构造函数来代替 `eval` 的使用。
@@ -120,18 +118,15 @@
> **注意:** 虽然也可以使用这样的语法 `setTimeout(foo, 1000, a, b, c)`
> 但是不推荐这么做,因为在使用对象的[属性方法](#function.this)时可能会出错。
->(译者注:这里说的是属性方法内,this 的指向错误)
-
+>**译者注:**这里说的是属性方法内,`this` 的指向错误)
-### 结论(In conclusion)
+###结论
**绝对不要**使用字符串作为 `setTimeout` 或者 `setInterval` 的第一个参数,
这么写的代码明显质量很差。当需要向回调函数传递参数时,可以创建一个*匿名函数*,在函数内执行真实的回调函数。
另外,应该避免使用 `setInterval`,因为它的定时执行不会被 JavaScript 阻塞。
-
[1]: http://en.wikipedia.org/wiki/Document_Object_Model
-
[30]: http://cnblogs.com/sanshi/
View
19 doc/zh/types/casting.md
@@ -1,4 +1,4 @@
-## 类型转换
+##类型转换
JavaScript 是*弱类型*语言,所以会在**任何**可能的情况下应用*强制类型转换*
@@ -21,8 +21,7 @@ JavaScript 是*弱类型*语言,所以会在**任何**可能的情况下应用
为了避免上面复杂的强制类型转换,**强烈**推荐使用[严格的等于操作符](#types.equality)。
虽然这可以避免大部分的问题,但 JavaScript 的弱类型系统仍然会导致一些其它问题。
-
-### 内置类型的构造函数(Constructors of built-in types)
+###内置类型的构造函数
内置类型(比如 `Number``String`)的构造函数在被调用时,使用或者不使用 `new` 的结果完全不同。
@@ -37,21 +36,19 @@ JavaScript 是*弱类型*语言,所以会在**任何**可能的情况下应用
最好的选择是把要比较的值**显式**的转换为三种可能的类型之一。
-
-### 转换为字符串(Casting to a string)
+###转换为字符串
'' + 10 === '10'; // true
将一个值加上空字符串可以轻松转换为字符串类型。
-
-### 转换为数字(Casting to a number)
+###转换为数字
+'10' === 10; // true
使用**一元**的加号操作符,可以把字符串转换为数字。
-[译者注][30]:字符串转换为数字的常用方法:
+**[译者注][30]:**字符串转换为数字的常用方法:
+'010' === 10
Number('010') === 10
@@ -62,7 +59,7 @@ JavaScript 是*弱类型*语言,所以会在**任何**可能的情况下应用
parseInt('010.2', 10) === 10
-### 转换为布尔型(Casting to a boolean)
+###转换为布尔型
通过使用 **否** 操作符两次,可以把一个值转换为布尔型。
@@ -74,6 +71,4 @@ JavaScript 是*弱类型*语言,所以会在**任何**可能的情况下应用
!!{}; // true
!!true; // true
-
-
-[30]: http://cnblogs.com/sanshi/
+[30]: http://cnblogs.com/sanshi/
View
16 doc/zh/types/equality.md
@@ -1,8 +1,8 @@
-## 相等与比较
+##相等与比较
JavaScript 有两种方式判断两个值是否相等。
-### 等于操作符(The equals operator)
+###等于操作符
等于操作符由两个等号组成:`==`
@@ -23,10 +23,9 @@ JavaScript 是*弱类型*语言,这就意味着,等于操作符会为了比
此外,强制类型转换也会带来性能消耗,比如一个字符串为了和一个数组进行比较,必须事先被强制转换为数字。
+###严格等于操作符
-### 严格的等于操作符(The strict equals operator)
-
-严格的等于操作符由**三**个等号组成:`===`
+严格等于操作符由**三**个等号组成:`===`
不想普通的等于操作符,严格的等于操作符**不会**进行强制类型转换。
@@ -42,8 +41,7 @@ JavaScript 是*弱类型*语言,这就意味着,等于操作符会为了比
上面的结果更加清晰并有利于代码的分析。如果两个操作数类型不同就肯定不相等也有助于性能的提升。
-
-### 比较对象(Comparing objects)
+###比较对象
虽然 `==``===` 操作符都是等于操作符,但是当其中有一个操作数为对象时,行为就不同了。
@@ -56,11 +54,11 @@ JavaScript 是*弱类型*语言,这就意味着,等于操作符会为了比
这里等于操作符比较的**不是**值是否相等,而是是否属于同一个**身份**;也就是说,只有对象的同一个实例才被认为是相等的。
这有点像 Python 中的 `is` 和 C 中的指针比较。
-### 结论(In conclusion)
+###结论
强烈推荐使用**严格的等于操作符**。如果类型需要转换,应该在比较之前[显式](#types.casting)的转换,
而不是使用语言本身复杂的强制转换规则。
-[30]: http://cnblogs.com/sanshi/
+[30]: http://cnblogs.com/sanshi/
View
12 doc/zh/types/instanceof.md
@@ -1,9 +1,9 @@
-## `instanceof` 操作符
+##`instanceof` 操作符
`instanceof` 操作符用来比较两个操作数的构造函数。只有在比较自定义的对象时才有意义。
如果用来比较内置类型,将会和 [typeof 操作符](#types.typeof) 一样用处不大。
-### 比较自定义对象(Comparing custom objects)
+###比较自定义对象
function Foo() {}
function Bar() {}
@@ -16,7 +16,7 @@
Bar.prototype = Foo;
new Bar() instanceof Foo; // false
-### `instanceof` 比较内置类型(Using `instanceof` with native types)
+###`instanceof` 比较内置类型
new String('foo') instanceof String; // true
new String('foo') instanceof Object; // true
@@ -27,11 +27,9 @@
有一点需要注意,`instanceof` 用来比较属于不同 JavaScript 上下文的对象(比如,浏览器中不同的文档结构)时将会出错,
因为它们的构造函数不会是同一个对象。
-
-### 结论(In conclusion)
+### 结论
`instanceof` 操作符应该**仅仅**用来比较来自同一个 JavaScript 上下文的自定义对象。
正如 [`typeof`](#types.typeof) 操作符一样,任何其它的用法都应该是避免的。
-
-[30]: http://cnblogs.com/sanshi/
+[30]: http://cnblogs.com/sanshi/
View
21 doc/zh/types/typeof.md
@@ -1,18 +1,16 @@
-## `typeof` 操作符
+##`typeof` 操作符
`typeof` 操作符(和 [`instanceof`](#types.instanceof) 一起)或许是 JavaScript 中最大的设计缺陷,
因为几乎不可能从它们那里得到想要的结果。
-尽管 `instanceof` 还有一些极少数的应用场景,`typeof` 只有一个实际的应用([译者注][30]:这个实际应用是用来检测一个对象是否已经定义或者是否已经赋值),
+尽管 `instanceof` 还有一些极少数的应用场景,`typeof` 只有一个实际的应用(**[译者注][30]:**这个实际应用是用来检测一个对象是否已经定义或者是否已经赋值),
而这个应用却**不是**用来检查对象的类型。
-
> **注意:** 由于 `typeof` 也可以像函数的语法被调用,比如 `typeof(obj)`,但这并是一个函数调用。
> 那两个小括号只是用来计算一个表达式的值,这个返回值会作为 `typeof` 操作符的一个操作数。
> 实际上**不存在**名为 `typeof` 的函数。
-
-### JavaScript 类型表格(The JavaScript type table)
+###JavaScript 类型表格
Value Class Type
-------------------------------------
@@ -42,8 +40,7 @@
为了获取对象的 `[[Class]]`,我们需要使用定义在 `Object.prototype` 上的方法 `toString`
-
-### 对象的类定义(The Class of an object)
+###对象的类定义
JavaScript 标准文档只给出了一种获取 `[[Class]]` 值的方法,那就是使用 `Object.prototype.toString`
@@ -57,19 +54,17 @@ JavaScript 标准文档只给出了一种获取 `[[Class]]` 值的方法,那
上面例子中,`Object.prototype.toString` 方法被调用,[this](#function.this) 被设置为了需要获取 `[[Class]]` 值的对象。
-
-[译者注][30]:`Object.prototype.toString` 返回一种标准格式字符串,所以上例可以通过 slice 截取指定位置的字符串,如下所示:
+**[译者注][30]:**`Object.prototype.toString` 返回一种标准格式字符串,所以上例可以通过 `slice` 截取指定位置的字符串,如下所示:
Object.prototype.toString.call([]) // "[object Array]"
Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call(2) // "[object Number]"
-
> **ES5 提示:** 在 ECMAScript 5 中,为了方便,对 `null``undefined` 调用 `Object.prototype.toString` 方法,
> 其返回值由 `Object` 变成了 `Null``Undefined`
-[译者注][30]:这种变化可以从 IE8 和 Firefox 4 中看出区别,如下所示:
+**[译者注][30]:**这种变化可以从 IE8 和 Firefox 4 中看出区别,如下所示:
// IE8
Object.prototype.toString.call(null) // "[object Object]"
@@ -80,15 +75,15 @@ JavaScript 标准文档只给出了一种获取 `[[Class]]` 值的方法,那
Object.prototype.toString.call(undefined) // "[object Undefined]"
-### 测试为定义变量(Testing for undefined variables)
+###测试为定义变量
typeof foo !== 'undefined'
上面代码会检测 `foo` 是否已经定义;如果没有定义而直接使用会导致 `ReferenceError` 的异常。
这是 `typeof` 唯一有用的地方。
-### 结论(In conclusion)
+###结论
为了检测一个对象的类型,强烈推荐使用 `Object.prototype.toString` 方法;
因为这是唯一一个可依赖的方式。正如上面表格所示,`typeof` 的一些返回值在标准文档中并未定义,
View
4 site/style/garden.css
@@ -346,6 +346,10 @@ aside p {
line-height: 1.3em;
}
+aside p + p {
+ margin-top: 1.5em;
+}
+
aside.es5:after {
content: 'ES5';
font-family: Georgia, serif;
View
347 site/zh/index.html
@@ -1,12 +1,12 @@
-<!DOCTYPE html><html lang="zh"><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"><!--[if lt IE 9]>
+<!DOCTYPE html><html lang="zh"><head><title>JavaScript 秘密花园</title><meta charset="utf-8"><meta name="description" content="JavaScript 语言最古怪用法的文档集合"><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 id="nav_main"><div><ul><li><a href="/JavaScript-Garden/ru" title="JavaScript Гарден по-русски">ru</a></li><li class="active"><a href="/JavaScript-Garden/zh" title="JavaScript Garden in English">zh</a></li><li><a href="/JavaScript-Garden/" title="JavaScript Garden in English">en</a></li></ul><a id="top" href="#intro" title="Back to top">#top</a><a id="hide_menu" class="tablet">Hide Menu</a></div><ul><li class="nav_intro"><h1><a href="#intro">简介</a></h1><ul><li><a href="#intro.authors"> 关于作者</a></li><li><a href="#intro.contributors"> 贡献者</a></li><li><a href="#intro.license"> 许可</a></li></ul></li><li class="nav_object"><h1><a href="#object">对象</a></h1><ul><li><a href="#object.general"> 对象使用和属性</a></li><li><a href="#object.prototype"> 原型</a></li><li><a href="#object.hasownproperty"> <code>hasOwnProperty</code> 函数</a></li><li><a href="#object.forinloop"> <code>for in</code> 循环</a></li></ul></li><li class="nav_function"><h1><a href="#function">函数</a></h1><ul><li><a href="#function.general"> 函数声明与表达式</a></li><li><a href="#function.this"> this 的工作原理</a></li><li><a href="#function.closures"> 闭包和引用</a></li><li><a href="#function.arguments"> <code>arguments</code> 对象</a></li><li><a href="#function.constructors"> 构造函数</a></li><li><a href="#function.scopes"> 作用域与命名空间</a></li></ul></li><li class="nav_array"><h1><a href="#array">数组</a></h1><ul><li><a href="#array.general"> 数组遍历与属性</a></li><li><a href="#array.constructor"> <code>Array</code> 构造函数</a></li></ul></li><li class="nav_types"><h1><a href="#types">类型</a></h1><ul><li><a href="#types.equality"> 相等与比较</a></li><li><a href="#types.typeof"> <code>typeof</code> 操作符</a></li><li><a href="#types.instanceof"> <code>instanceof</code> 操作符</a></li><li><a href="#types.casting"> 类型转换</a></li></ul></li><li class="nav_core"><h1><a href="#core">核心</a></h1><ul><li><a href="#core.eval"> 为什么不要使用 <code>eval</code></a></li><li><a href="#core.undefined"> <code>undefined</code> 和 <code>null</code></a></li><li><a href="#core.semicolon"> 自动分号插入</a></li></ul></li><li class="nav_other"><h1><a href="#other">其它</a></h1><ul><li><a href="#other.timeouts"> <code>setTimeout</code> 和 <code>setInterval</code></a></li></ul></li></ul></nav><!-- Mobile navigation--><nav id="nav_mobile"><a id="nav_prev_section" href="#">prev section<span class="nav_section_name">section name</span></a><a id="nav_next_section" href="#">next section<span class="nav_section_name">section name</span></a><a id="show_menu">show menu</a></nav><!-- Sections--><section id="intro"><!-- Introduction--><header id="intro.intro"><h1>简介</h1><div><p><strong>JavaScript 秘密花园</strong>是一个不断更新的文档,主要关心 JavaScript 一些古怪用法。
+</head><body><!-- Navigation--><nav id="nav_main"><div><ul><li><a href="/JavaScript-Garden/ru" title="JavaScript Гарден по-русски">ru</a></li><li class="active"><a href="/JavaScript-Garden/zh" title="JavaScript Garden 中文翻译">zh</a></li><li><a href="/JavaScript-Garden/" title="JavaScript Garden in English">en</a></li></ul><a id="top" href="#intro" title="Back to top">#top</a><a id="hide_menu" class="tablet">Hide Menu</a></div><ul><li class="nav_intro"><h1><a href="#intro">简介</a></h1><ul><li><a href="#intro.authors"> 关于作者</a></li><li><a href="#intro.contributors"> 贡献者</a></li><li><a href="#intro.license"> 许可</a></li></ul></li><li class="nav_object"><h1><a href="#object">对象</a></h1><ul><li><a href="#object.general">对象使用和属性</a></li><li><a href="#object.prototype">原型</a></li><li><a href="#object.hasownproperty"><code>hasOwnProperty</code> 函数</a></li><li><a href="#object.forinloop"><code>for in</code> 循环</a></li></ul></li><li class="nav_function"><h1><a href="#function">函数</a></h1><ul><li><a href="#function.general">函数声明与表达式</a></li><li><a href="#function.this"><code>this</code> 的工作原理</a></li><li><a href="#function.closures">闭包和引用</a></li><li><a href="#function.arguments"><code>arguments</code> 对象</a></li><li><a href="#function.constructors">构造函数</a></li><li><a href="#function.scopes">作用域与命名空间</a></li></ul></li><li class="nav_array"><h1><a href="#array">数组</a></h1><ul><li><a href="#array.general">数组遍历与属性</a></li><li><a href="#array.constructor"><code>Array</code> 构造函数</a></li></ul></li><li class="nav_types"><h1><a href="#types">类型</a></h1><ul><li><a href="#types.equality">相等与比较</a></li><li><a href="#types.typeof"><code>typeof</code> 操作符</a></li><li><a href="#types.instanceof"><code>instanceof</code> 操作符</a></li><li><a href="#types.casting">类型转换</a></li></ul></li><li class="nav_core"><h1><a href="#core">核心</a></h1><ul><li><a href="#core.eval">为什么不要使用 <code>eval</code></a></li><li><a href="#core.undefined"><code>undefined</code> 和 <code>null</code></a></li><li><a href="#core.semicolon">自动分号插入</a></li></ul></li><li class="nav_other"><h1><a href="#other">其它</a></h1><ul><li><a href="#other.timeouts"><code>setTimeout</code> 和 <code>setInterval</code></a></li></ul></li></ul></nav><!-- Mobile navigation--><nav id="nav_mobile"><a id="nav_prev_section" href="#">prev section<span class="nav_section_name">section name</span></a><a id="nav_next_section" href="#">next section<span class="nav_section_name">section name</span></a><a id="show_menu">show menu</a></nav><!-- Sections--><section id="intro"><!-- Introduction--><header id="intro.intro"><h1>简介</h1><div><p><strong>JavaScript 秘密花园</strong>是一个不断更新,主要关心 JavaScript 一些古怪用法的文档。
对于如何避免常见的错误,难以发现的问题,以及性能问题和不好的实践给出建议,
初学者可以籍此深入了解 JavaScript 的语言特性。</p>
<p>JavaScript 秘密花园<strong>不是</strong>用来教你 JavaScript。为了更好的理解这篇文章的内容,
-你需要事先学习 JavaScript 的基础知识。在 Mozilla 开发者网络中有一系列非常棒的 JavaScript 学习<a href="https://developer.mozilla.org/en/JavaScript/Guide">向导</a>。</p></div></header><!-- Articles--><article id="intro.authors"><h2> 关于作者</h2><div><p>这篇文章的作者是两位 Stack Overflow 的用户, <a href="http://stackoverflow.com/users/170224/ivo-wetzel">Ivo Wetzel</a> (写作) 和 <a href="http://stackoverflow.com/users/313758/yi-jiang">Zhang Yi Jiang</a> (设计)。</p></div></article><article id="intro.contributors"><h2> 贡献者</h2><div><ul>
+你需要事先学习 JavaScript 的基础知识。在 Mozilla 开发者网络中有一系列非常棒的 JavaScript 学习<a href="https://developer.mozilla.org/en/JavaScript/Guide">向导</a>。</p></div></header><!-- Articles--><article id="intro.authors"><h2> 关于作者</h2><div><p>这篇文章的作者是两位 <a href="http://stackoverflow.com/">Stack Overflow</a> 用户, <a href="http://stackoverflow.com/users/170224/ivo-wetzel">伊沃·韦特泽尔 Ivo Wetzel</a>(写作) 和 <a href="http://stackoverflow.com/users/313758/yi-jiang">张易江 Zhang Yi Jiang</a>(设计)。</p></div></article><article id="intro.contributors"><h2> 贡献者</h2><div><ul>
<li><a href="https://github.com/caio">Caio Romão</a> (拼写检查)</li>
<li><a href="https://github.com/blixt">Andreas Blixt</a> (语言修正)</li>
</ul>
@@ -17,9 +17,9 @@
<li><a href="http://sanshi.me/">三生石上</a></li>
</ul>
-<p>此中文翻译由<a href="http://sanshi.me/">三生石上</a>独立完成,<a href="http://cnblogs.com/sanshi/">博客园</a>首发,转载请注明出处。</p></div></article><article id="intro.license"><h2> 许可</h2><div><p>JavaScript 秘密花园在 <a href="https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE">MIT license</a> 许可协议下发布,并存放在开源社区 <a href="https://github.com/BonsaiDen/JavaScript-Garden">GitHub</a>。
-如果你发现错误或者打字错误,请 <a href="https://github.com/BonsaiDen/JavaScript-Garden/issues">file an issue</a> 或者 pull request
-你也可以在 Stack Overflow 的聊天室 <a href="http://chat.stackoverflow.com/rooms/17/javascript">JavaScript room</a> 找到我们。</p></div></article></section><section id="object"><!-- Introduction--><header id="object.intro"><h1>对象</h1></header><!-- Articles--><article id="object.general"><h2> 对象使用和属性</h2><div><p>JavaScript 中所有变量都是对象,除了两个例外 <a href="#undefined"><code>null</code></a> 和 <a href="#undefined"><code>undefined</code></a>。</p>
+<p>此中文翻译由<a href="http://sanshi.me/">三生石上</a>独立完成,<a href="http://cnblogs.com/sanshi/">博客园</a>首发,转载请注明出处。</p></div></article><article id="intro.license"><h2> 许可</h2><div><p>JavaScript 秘密花园在 <a href="https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE">MIT license</a> 许可协议下发布,并存放在 <a href="https://github.com/BonsaiDen/JavaScript-Garden">GitHub</a> 开源社区
+如果你发现错误或者打字错误,请<a href="https://github.com/BonsaiDen/JavaScript-Garden/issues">新建一个任务单</a>或者发一个抓取请求
+你也可以在 Stack Overflow <a href="http://chat.stackoverflow.com/rooms/17/javascript">JavaScript 聊天室</a> 找到我们。</p></div></article></section><section id="object"><!-- Introduction--><header id="object.intro"><h1>对象</h1></header><!-- Articles--><article id="object.general"><h2>对象使用和属性</h2><div><p>JavaScript 中所有变量都是对象,除了两个例外 <a href="#undefined"><code>null</code></a> 和 <a href="#undefined"><code>undefined</code></a>。</p>
<pre><code>false.toString() // &#39;false&#39;
[1, 2, 3].toString(); // &#39;1,2,3&#39;
@@ -42,7 +42,7 @@
(2).toString(); // 2先被计算
</code></pre>
-</div><div><h3>对象作为数据类型(Objects as a data type)</h3>
+</div><div><h3>对象作为数据类型</h3>
<p>JavaScript 的对象可以作为<a href="http://en.wikipedia.org/wiki/Hashmap"><em>哈希表</em></a>使用,主要用来保存命名的键与值的对应关系。</p>
@@ -55,7 +55,7 @@
var bar = {test: 12};
</code></pre>
-</div><div><h3>访问属性(Accessing properties)</h3>
+</div><div><h3>访问属性</h3>
<p>有两种方式来访问对象的属性,点操作符或者中括号操作符。</p>
@@ -72,11 +72,13 @@
<p>两种语法是等价的,但是中括号操作符在下面两种情况下依然有效
- 动态设置属性
- - 属性名不是一个有效的变量名(<a href="http://cnblogs.com/sanshi/">译者注</a>:比如属性名中包含空格,或者属性名是JS的关键词)</p>
+ - 属性名不是一个有效的变量名(<strong><a href="http://cnblogs.com/sanshi/">译者注</a>:</strong>比如属性名中包含空格,或者属性名是 JS 的关键词)</p>
-<p><a href="http://cnblogs.com/sanshi/">译者注</a>:在 <a href="http://www.jslint.com/">JSLint</a> 语法检测工具中,点操作符是推荐做法。</p>
+<aside>
+ <p><strong><a href="http://cnblogs.com/sanshi/">译者注</a>:</strong>在 <a href="http://www.jslint.com/">JSLint</a> 语法检测工具中,点操作符是推荐做法。</p>
+</aside>
-</div><div><h3>删除属性(Deleting properties)</h3>
+</div><div><h3>删除属性</h3>
<p>删除属性的唯一方法是使用 <code>delete</code> 操作符;设置属性为 <code>undefined</code> 或者 <code>null</code> 并不能真正的删除属性,
而<strong>仅仅</strong>是移除了属性和值的关联。</p>
@@ -99,7 +101,7 @@
<p>上面的输出结果有 <code>bar undefined</code> 和 <code>foo null</code> - 只有 <code>baz</code> 被真正的删除了,所以从输出结果中消失。</p>
-</div><div><h3>属性名的语法(Notation of keys)</h3>
+</div><div><h3>属性名的语法</h3>
<pre><code>var test = {
&#39;case&#39;: &#39;I am a keyword so I must be notated as a string&#39;,
@@ -111,12 +113,12 @@
上面的第二种声明方式在 ECMAScript 5 之前会抛出 <code>SyntaxError</code> 的错误。</p>
<p>这个错误的原因是 <code>delete</code> 是 JavaScript 语言的一个<em>关键词</em>;因此为了在更低版本的 JavaScript 引擎下也能正常运行,
-必须使用<em>字符串字面值</em>声明方式。</p></div></article><article id="object.prototype"><h2> 原型</h2><div><p>JavaScript 不包含传统的类继承模型,而是使用 <em>prototypical</em> 原型模型。</p>
+必须使用<em>字符串字面值</em>声明方式。</p></div></article><article id="object.prototype"><h2>原型</h2><div><p>JavaScript 不包含传统的类继承模型,而是使用 <em>prototypal</em> 原型模型。</p>
<p>虽然这经常被当作是 JavaScript 的缺点被提及,其实基于原型的继承模型比传统的类继承还要强大。
实现传统的类继承模型是很简单,但是实现 JavaScript 中的原型继承则要困难的多。
-It is for example fairly trivial to build a classic model on top of it, while the
-other way around is a far more difficult task.</p>
+(It is for example fairly trivial to build a classic model on top of it, while the
+other way around is a far more difficult task.)</p>
<p>由于 JavaScript 是唯一一个被广泛使用的基于原型继承的语言,所以理解两种继承模式的差异是需要一定时间的。</p>
@@ -158,26 +160,26 @@
<p>上面的例子中,<code>test</code> 对象从 <code>Bar.prototype</code> 和 <code>Foo.prototype</code> 继承下来;因此,
它能否访问 <code>Foo</code> 的原型方法 <code>method</code>。但是它不能访问 <code>Foo</code> 的实例属性 <code>value</code>,
因为这个属性在<code>Foo</code>的<a href="#constructor">构造函数</a>中定义。
-But it will not have access to the property <code>value</code> of a
+(But it will not have access to the property <code>value</code> of a
<code>Foo</code> instance, since that property gets defined in the <a href="#constructor">constructor</a>
-of <code>Foo</code>. But this constructor has to be called explicitly.)</p>
-
-<p><a href="http://cnblogs.com/sanshi/">译者注</a>:我认为这个描述是错误的,test.value 是可以访问的。
-因为在设置 Bar.prototype = new Foo(); 时,<code>value</code> 也就成为 Bar.prototype 上的一个属性。
-如果你有不同观点,可以到<a href="http://cnblogs.com/sanshi/">我的博客</a>评论。</p>
+of <code>Foo</code>. But this constructor has to be called explicitly.)</p>
<aside>
+ <p><strong><a href="http://cnblogs.com/sanshi/">译者注</a>:</strong>我认为这个描述是错误的,<code>test.value</code> 是可以访问的。
+ 因为在设置 <code>Bar.prototype = new Foo();</code> 时,<code>value</code> 也就成为 <code>Bar.prototype</code> 上的一个属性。
+ 如果你有不同观点,可以到<a href="http://cnblogs.com/sanshi/">我的博客</a>评论。</p>
+
<p><strong>注意:</strong> <strong>不要</strong>使用 <code>Bar.prototype = Foo</code>,因为这不会执行 <code>Foo</code> 的原型,而是指向函数 <code>Foo</code>。
因此原型链将会回溯到 <code>Function.prototype</code> 而不是 <code>Foo.prototype</code>,因此 <code>method</code> 将不会在 Bar 的原型链上。</p>
</aside>
-</div><div><h3>属性查找(Property lookup)</h3>
+</div><div><h3>属性查找</h3>
<p>当查找一个对象的属性时,JavaScript 会<strong>向上</strong>遍历原型链,直到找到给定名称的属性为止。</p>
<p>到查找到达原型链的顶部 - 也就是 <code>Object.prototype</code> - 但是仍然没有找到指定的属性,就会返回 <a href="#undefined">undefined</a>。</p>
-</div><div><h3>原型属性(The prototype property)</h3>
+</div><div><h3>原型属性</h3>
<p>当原型属性用来创建原型链时,可以把<strong>任何</strong>类型的值赋给它(prototype)。
然而将原子类型赋给 prototype 的操作将会被忽略。</p>
@@ -188,13 +190,13 @@
<p>而将对象赋值给 prototype,正如上面的例子所示,将会动态的创建原型链。</p>
-</div><div><h3>性能(Performance)</h3>
+</div><div><h3>性能</h3>
<p>如果一个属性在原型链的上端,则对于查找时间将带来不利影响。特别的,试图获取一个不存在的属性将会遍历整个原型链。</p>
<p>并且,当使用 <a href="#the-for-in-loop">for-in</a> 循环遍历对象的属性时,原型链上的<strong>所有</strong>属性都将被访问。</p>
-</div><div><h3>扩展内置类型的原型(Extension of native prototypes)</h3>
+</div><div><h3>扩展内置类型的原型</h3>
<p>一个错误特性被经常使用,那就是扩展 <code>Object.prototype</code> 或者其他内置类型的原型对象。</p>
@@ -203,21 +205,23 @@
<p>扩展内置类型的<strong>唯一</strong>理由是为了和新的 JavaScript 保持一致,比如 <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach"><code>Array.forEach</code></a>。</p>
-<p><a href="http://cnblogs.com/sanshi/">译者注</a>:这是编程领域常用的一种方式,称之为 <a href="http://en.wikipedia.org/wiki/Backport">Backport</a>,也就是将新的补丁添加到老版本中。</p>
+<aside>
+ <p><strong><a href="http://cnblogs.com/sanshi/">译者注</a>:</strong>这是编程领域常用的一种方式,称之为 <a href="http://en.wikipedia.org/wiki/Backport">Backport</a>,也就是将新的补丁添加到老版本中。</p>
+</aside>
-</div><div><h3>总结(In conclusion)</h3>
+</div><div><h3>总结</h3>
<p>在写复杂的 JavaScript 应用之前,充分理解原型链继承的工作方式是每个 JavaScript 程序员<strong>必修</strong>的功课。
要提防原型链过长带来的性能问题,并知道如何通过缩短原型链来提高性能。
-更进一步,绝对<strong>不要</strong>扩展内置类型的原型,除非是为了和新的 JavaScript 引擎兼容。</p></div></article><article id="object.hasownproperty"><h2> <code>hasOwnProperty</code> 函数</h2><div><p>为了判断一个对象是否包含<em>自定义</em>属性而<em>不是</em><a href="#prototype">原型链</a>上的属性,
+更进一步,绝对<strong>不要</strong>扩展内置类型的原型,除非是为了和新的 JavaScript 引擎兼容。</p></div></article><article id="object.hasownproperty"><h2><code>hasOwnProperty</code> 函数</h2><div><p>为了判断一个对象是否包含<em>自定义</em>属性而<em>不是</em><a href="#prototype">原型链</a>上的属性,
我们需要使用继承自 <code>Object.prototype</code> 的 <code>hasOwnProperty</code> 方法。</p>
<aside>
<p><strong>注意:</strong> 通过判断一个属性是否 <code>undefined</code> 是<strong>不够</strong>的。
因为一个属性可能确实存在,只不过它的值被设置为 <code>undefined</code>。</p>
</aside>
-<p><code>hasOwnProperty</code> 是JavaScript中唯一一个处理属性但是<strong>不需要</strong>查找原型链的方法。</p>
+<p><code>hasOwnProperty</code> 是 JavaScript 中唯一一个处理属性但是<strong></strong>查找原型链的函数。</p>
<pre><code>// 修改Object.prototype
Object.prototype.bar = 1;
@@ -233,7 +237,7 @@
<p>只有 <code>hasOwnProperty</code> 可以给出正确和期望的结果,这在遍历对象的属性时会很有用。
<strong>没有</strong>其它方法可以用来排除原型链上的属性,而不是定义在对象<em>自身</em>上的属性。</p>
-</div><div><h3><code>hasOwnProperty</code> 作为属性(<code>hasOwnProperty</code> as a property)</h3>
+</div><div><h3><code>hasOwnProperty</code> 作为属性</h3>
<p>JavaScript <strong>不会</strong>保护 <code>hasOwnProperty</code> 被非法占用,因此如果一个对象碰巧存在这个属性,
就需要使用<em>外部</em>的 <code>hasOwnProperty</code> 函数来获取正确的结果。</p>
@@ -251,11 +255,11 @@
{}.hasOwnProperty.call(foo, &#39;bar&#39;); // true
</code></pre>
-</div><div><h3>结论(In conclusion)</h3>
+</div><div><h3>结论</h3>
<p>当检查对象上某个属性是否存在时,<code>hasOwnProperty</code> 是<strong>唯一</strong>可用的方法。
同时在使用 <a href="#forinloop"><code>for in</code> loop</a> 遍历对象时,推荐<strong>总是</strong>使用 <code>hasOwnProperty</code> 方法,
-这将会避免<a href="#prototype">原型</a>对象扩展带来的干扰。</p></div></article><article id="object.forinloop"><h2> <code>for in</code> 循环</h2><div><p>和 <code>in</code> 操作符一样,<code>for in</code> 循环同样在查找对象属性时遍历原型链上的所有属性。</p>
+这将会避免<a href="#prototype">原型</a>对象扩展带来的干扰。</p></div></article><article id="object.forinloop"><h2><code>for in</code> 循环</h2><div><p>和 <code>in</code> 操作符一样,<code>for in</code> 循环同样在查找对象属性时遍历原型链上的所有属性。</p>
<aside>
<p><strong>注意:</strong> <code>for in</code> 循环<strong>不会</strong>遍历那些 <code>enumerable</code> 设置为 <code>false</code> 的属性;比如数组的 <code>length</code> 属性。</p>
@@ -277,7 +281,7 @@
<p><strong>注意:</strong> 由于 <code>for in</code> 总是要遍历整个原型链,因此如果一个对象的继承层次太深的话会影响性能。</p>
</aside>
-</div><div><h3>使用 <code>hasOwnProperty</code> 过滤(Using <code>hasOwnProperty</code> for filtering)</h3>
+</div><div><h3>使用 <code>hasOwnProperty</code> 过滤</h3>
<pre><code>// foo 变量是上例中的
for(var i in foo) {
@@ -293,12 +297,12 @@
<p>一个广泛使用的类库 <a href="http://www.prototypejs.org/">Prototype</a> 就扩展了原生的 JavaScript 对象。
因此,但这个类库被包含在页面中时,不使用 <code>hasOwnProperty</code> 过滤的 <code>for in</code> 循环难免会出问题。</p>
-</div><div><h3>最佳实践(Best practices)</h3>
+</div><div><h3>总结</h3>
-<p>推荐<strong>总是</strong>使用 <code>hasOwnProperty</code>。不要对代码运行的环境做任何假设,不要假设原生对象是否已经被扩展了。</p></div></article></section><section id="function"><!-- Introduction--><header id="function.intro"><h1>函数</h1></header><!-- Articles--><article id="function.general"><h2> 函数声明与表达式</h2><div><p>函数是JavaScript中的一等对象,这意味着可以把函数像其它值一样传递。
+<p>推荐<strong>总是</strong>使用 <code>hasOwnProperty</code>。不要对代码运行的环境做任何假设,不要假设原生对象是否已经被扩展了。</p></div></article></section><section id="function"><!-- Introduction--><header id="function.intro"><h1>函数</h1></header><!-- Articles--><article id="function.general"><h2>函数声明与表达式</h2><div><p>函数是JavaScript中的一等对象,这意味着可以把函数像其它值一样传递。
一个常见的用法是把<em>匿名函数</em>作为回调函数传递对异步函数中。</p>
-</div><div><h3>函数声明(The <code>function</code> declaration)</h3>
+</div><div><h3>函数声明</h3>
<pre><code>function foo() {}
</code></pre>
@@ -310,7 +314,7 @@
function foo() {}
</code></pre>
-</div><div><h3>函数赋值表达式(The <code>function</code> expression)</h3>
+</div><div><h3>函数赋值表达式</h3>
<pre><code>var foo = function() {};
</code></pre>
@@ -326,7 +330,7 @@
<p>但是由于赋值语句只在运行时执行,因此在相应代码执行之前, <code>foo</code> 的值缺省为 <a href="#undefined">undefined</a>。</p>
-</div><div><h3>命名函数的赋值表达式(Named function expression)</h3>
+</div><div><h3>命名函数的赋值表达式</h3>
<p>另外一个特殊的情况是将命名函数赋值给一个变量。</p>
@@ -338,19 +342,21 @@
<p><code>bar</code> 函数声明外是不可见的,这是因为我们已经把函数赋值给了 <code>foo</code>;
然而在 <code>bar</code> 内部依然可见。这是由于 JavaScript 的 <a href="#scopes">命名处理</a> 所致,
-函数名在函数内<em>总是</em>可见的。</p></div></article><article id="function.this"><h2> this 的工作原理</h2><div><p>JavaScript 有一套完全不同于其它语言的对 <code>this</code> 的处理机制。
+函数名在函数内<em>总是</em>可见的。</p></div></article><article id="function.this"><h2><code>this</code> 的工作原理</h2><div><p>JavaScript 有一套完全不同于其它语言的对 <code>this</code> 的处理机制。
在<strong>五</strong>种不同的情况下 ,<code>this</code> 指向的各不相同。</p>
-</div><div><h3>全局范围内(The global scope)</h3>
+</div><div><h3>全局范围内</h3>
<pre><code>this;
</code></pre>
<p>当在全部范围内使用 <code>this</code>,它将会指向<em>全局</em>对象。</p>
-<p><a href="http://cnblogs.com/sanshi/">译者注</a>:浏览器中运行的JavaScript脚本,这个全局对象是 window。</p>
+<aside>
+ <p><strong><a href="http://cnblogs.com/sanshi/">译者注</a>:</strong>浏览器中运行的 JavaScript 脚本,这个全局对象是 <code>window</code>。</p>
+</aside>
-</div><div><h3>函数调用(Calling a function)</h3>
+</div><div><h3>函数调用</h3>
<pre><code>foo();
</code></pre>
@@ -362,22 +368,22 @@
<a href="http://cnblogs.com/sanshi/">译者注</a>:ES5指的是ECMAScript 5,是 2009-12 发布的最新的 JavaScript 版本。</p>
</aside>
-</div><div><h3>方法调用(Calling a method)</h3>
+</div><div><h3>方法调用</h3>
<pre><code>test.foo();
</code></pre>
<p>这个例子中,<code>this</code> 指向 <code>test</code> 对象。</p>
-</div><div><h3>调用构造函数(Calling a constructor)</h3>
+</div><div><h3>调用构造函数</h3>
<pre><code>new foo();
</code></pre>
<p>如果函数倾向于和 <code>new</code> 关键词一块使用,则我们称这个函数是 <a href="#constructors">构造函数</a>。
在函数内部,<code>this</code> 指向<em>新创建</em>的对象。</p>
-</div><div><h3>显式的设置 <code>this</code>(Explicit setting of <code>this</code>)</h3>
+</div><div><h3>显式的设置 <code>this</code></h3>
<pre><code>function foo(a, b, c) {}
@@ -394,17 +400,17 @@
<aside>
<p><strong>注意:</strong> 在对象的字面声明语法中,<code>this</code> <strong>不能</strong>用来指向对象本身。
因此 <code>var obj = {me: this}</code> 中的 <code>me</code> 不会指向 <code>obj</code>,因为 <code>this</code> 只可能出现在上述的五种情况中。
- <a href="http://cnblogs.com/sanshi/">译者注</a>:这个例子中,如果是在浏览器中运行,obj.me等于window对象。</p>
+ <strong><a href="http://cnblogs.com/sanshi/">译者注</a>:</strong>这个例子中,如果是在浏览器中运行,<code>obj.me</code> 等于 <code>window</code> 对象。</p>
</aside>
-</div><div><h3>常见误解(Common pitfalls)</h3>
+</div><div><h3>常见误解</h3>
-<p>尽管大部分的情况都说的过去,不过第一个规则(<a href="http://cnblogs.com/sanshi/">译者注</a>:这里指的应该是第二个规则,也就是直接调用函数时,<code>this</code> 指向全局对象)
+<p>尽管大部分的情况都说的过去,不过第一个规则(<strong><a href="http://cnblogs.com/sanshi/">译者注</a>:</strong>这里指的应该是第二个规则,也就是直接调用函数时,<code>this</code> 指向全局对象)
被认为是JavaScript语言另一个错误设计的地方,因为它<strong>从来</strong>就没有实际的用途。</p>
<pre><code>Foo.method = function() {
function test() {
- // this 将会被设置为全局对象([译者注][30]:浏览器环境中也就是 window 对象)
+ // this 将会被设置为全局对象(译者注:浏览器环境中也就是 window 对象)
}
test();
}
@@ -424,9 +430,9 @@
</code></pre>
<p><code>that</code> 只是我们随意起的名字,不过这个名字被广泛的用来指向外部的 <code>this</code> 对象。
-在 <a href="#closures">closures</a> 一节,我们可以看到 <code>that</code> 可以作为参数传递。</p>
+在 <a href="#closures">闭包</a> 一节,我们可以看到 <code>that</code> 可以作为参数传递。</p>
-</div><div><h3>方法的赋值表达式(Assigning methods)</h3>
+</div><div><h3>方法的赋值表达式</h3>
<p>另一个看起来奇怪的地方是函数别名,也就是将一个方法<strong>赋值</strong>给一个变量。</p>
@@ -447,10 +453,10 @@
new Bar().method();
</code></pre>
-<p>当 <code>method</code> 被调用时,<code>this</code> 将会指向 <code>Bar</code> 的实例对象。</p></div></article><article id="function.closures"><h2> 闭包和引用</h2><div><p>闭包是 JavaScript 一个非常重要的特性,这意味着当前作用域<strong>总是</strong>能够访问外部作用域中的变量。
+<p>当 <code>method</code> 被调用时,<code>this</code> 将会指向 <code>Bar</code> 的实例对象。</p></div></article><article id="function.closures"><h2>闭包和引用</h2><div><p>闭包是 JavaScript 一个非常重要的特性,这意味着当前作用域<strong>总是</strong>能够访问外部作用域中的变量。
因为 <a href="#scopes">函数</a> 是 JavaScript 中唯一拥有自身作用域的结构,因此闭包的创建依赖于函数。</p>
-</div><div><h3>模拟私有变量(Emulating private variables)</h3>
+</div><div><h3>模拟私有变量</h3>
<pre><code>function Counter(start) {
var count = start;
@@ -473,7 +479,7 @@
<p>这里,<code>Counter</code> 函数返回两个闭包,函数 <code>increment</code> 和函数 <code>get</code>。 这两个函数都维持着
对外部作用域 <code>Counter</code> 的引用,因此总可以访问此作用域内定义的变量 <code>count</code>.</p>
-</div><div><h3>为什么不可以在外部访问私有变量(Why private variables work)</h3>
+</div><div><h3>为什么不可以在外部访问私有变量</h3>
<p>因为 JavaScript 中不可以对作用域进行引用或赋值,因此没有办法在外部访问 <code>count</code> 变量。
唯一的途径就是通过那两个闭包。</p>
@@ -487,10 +493,9 @@
<p>上面的代码<strong>不会</strong>改变定义在 <code>Counter</code> 作用域中的 <code>count</code> 变量的值,因为 <code>foo.hack</code> 没有
定义在那个<strong>作用域</strong>内。它将会创建或者覆盖<em>全局</em>变量 <code>count</code>。</p>
-</div><div><h3>循环中的闭包(Closures inside loops)</h3>
+</div><div><h3>循环中的闭包</h3>
-<p>一个常见的错误出现在循环中使用闭包,假设我们需要在每次循环中调用循环序号(as if they were
-copying the value of the loops index variable.)。</p>
+<p>一个常见的错误出现在循环中使用闭包,假设我们需要在每次循环中调用循环序号</p>
<pre><code>for(var i = 0; i &lt; 10; i++) {
setTimeout(function() {
@@ -501,13 +506,13 @@
<p>上面的代码不会输出数字 <code>0</code> 到 <code>9</code>,而是会输出数字 <code>10</code> 十次。</p>
-<p>当 <code>console.log</code> 被调用的时候,<em>匿名</em>函数保持对外部变量 <code>i</code> 的引用,此时 <code>for 循环</code>已经结束, <code>i</code> 的值被修改成了 <code>10</code>. </p>
+<p>当 <code>console.log</code> 被调用的时候,<em>匿名</em>函数保持对外部变量 <code>i</code> 的引用,此时 <code>for</code>循环已经结束, <code>i</code> 的值被修改成了 <code>10</code>. </p>
<p&