From 8a223e4413a1ce95e000dbaf04c0f45096abdd05 Mon Sep 17 00:00:00 2001 From: Ruan Yifeng Date: Sun, 8 Feb 2015 20:48:39 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9let?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/function.md | 9 +++++ docs/let.md | 98 +++++++++++++++++++++++++++++++++++++++++++++-- docs/reference.md | 2 + 3 files changed, 105 insertions(+), 4 deletions(-) diff --git a/docs/function.md b/docs/function.md index b5d7cf0..ecf8f7d 100644 --- a/docs/function.md +++ b/docs/function.md @@ -375,6 +375,15 @@ var d = new Date(...dateFields); 上面代码从数据库取出一行数据,通过扩展运算符,直接将其传入构造函数Date。 +除了扩展数组,扩展运算符还可以将一个数值扩展成数值。 + +```javascript + +[...5] +// [0, 1, 2, 3, 4, 5] + +``` + 扩展运算符还可以将字符串转为真正的数组。 ```javascript diff --git a/docs/let.md b/docs/let.md index 0f8064a..9cd7e0a 100644 --- a/docs/let.md +++ b/docs/let.md @@ -88,20 +88,85 @@ if (1) { 上面代码中,由于块级作用域内typeof运行时,x还没有声明,所以会抛出一个ReferenceError。 +总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称TDZ)。 + +```javascript + +if (true) { + // TDZ开始 + tmp = 'abc'; // ReferenceError + console.log(tmp); // ReferenceError + + let tmp; // TDZ结束 + console.log(tmp); // undefined + + tmp = 123; + console.log(tmp); // 123 +} + +``` + +上面代码中,在let命令声明变量tmp之前,都属于变量tmp的“死区”。 + +有些“死区”比较隐蔽,不太容易发现。 + +```javascript + +function bar(x=y, y=2) { + return [x, y]; +} + +bar(); // 报错 + +``` + +上面代码中,调用bar函数之所以报错,是因为参数x默认值等于另一个参数y,而此时y还没有声明,属于”死区“。 + +```javascript + +let foo = 'outer'; + +function bar(func = x => foo) { + let foo = 'inner'; + console.log(func()); // outer +} + +bar(); + +``` + +上面代码中,函数bar的参数func,默认是一个匿名函数,返回值为foo。这个匿名函数运行时,foo只在函数体外声明,内层的声明还没执行,因此foo指向函数体外的声明,输出outer。 + 注意,let不允许在相同作用域内,重复声明同一个变量。 ```javascript // 报错 { - let a = 10; - var a = 1; + let a = 10; + var a = 1; } // 报错 { - let a = 10; - let a = 1; + let a = 10; + let a = 1; +} + +``` + +因此,不能在函数内部重新声明参数。 + +```javascript + +function func(arg) { + let arg; // 报错 +} + +function func(arg) { + { + let arg; // 不报错 + } } ``` @@ -205,3 +270,28 @@ const message = "Goodbye!"; const age = 30; ``` + +由于const命令只是指向变量所在的地址,所以将一个对象声明为常量必须非常小心。 + +```javascript + +const foo = {}; +foo.prop = 123; + +foo.prop +// 123 + +foo = {} // 不起作用 + +``` + +上面代码中,常量foo储存的是一个地址,这个地址指向一个对象。不可变的只是这个地址,即不能把foo指向另一个地址,但对象本身是可变的,所以依然可以为其添加新属性。如果真的想将对象冻结,应该使用Object.freeze方法。 + +```javascript + +const foo = Object.freeze({}); +foo.prop = 123; // 不起作用 + +``` + +上面代码中,常量foo指向一个冻结的对象,所以添加新属性不起作用。 diff --git a/docs/reference.md b/docs/reference.md index 0bb3e72..d89a6d9 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -26,6 +26,7 @@ - Kyle Simpson, [For and against `let`](http://davidwalsh.name/for-and-against-let): 讨论let命令的作用域 - kangax, [Why `typeof` is no longer “safe”](http://es-discourse.com/t/why-typeof-is-no-longer-safe/15): 讨论在块级作用域内,let命令的变量声明和赋值的行为 +- Axel Rauschmayer, [Variables and scoping in ECMAScript 6](http://www.2ality.com/2015/02/es6-scoping.html): 讨论块级作用域与let和const的行为 - Nick Fitzgerald, [Destructuring Assignment in ECMAScript 6](http://fitzgeraldnick.com/weblog/50/): 详细介绍解构赋值的用法 - Nicholas C. Zakas, [Understanding ECMAScript 6 arrow functions](http://www.nczonline.net/blog/2013/09/10/understanding-ecmascript-6-arrow-functions/) - Jack Franklin, [Real Life ES6 - Arrow Functions](http://javascriptplayground.com/blog/2014/04/real-life-es6-arrow-fn/) @@ -66,6 +67,7 @@ - Jan Krems, [Generators Are Like Arrays](https://gist.github.com/jkrems/04a2b34fb9893e4c2b5c): 讨论Generator可以被当作数据结构看待 - Harold Cooper, [Coroutine Event Loops in Javascript](http://syzygy.st/javascript-coroutines/): Generator用于实现状态机 - Ruslan Ismagilov, [learn-generators](https://github.com/isRuslan/learn-generators): 编程练习,共6道题 +- Kyle Simpson, [Iterating ES6 Numbers](http://blog.getify.com/iterating-es6-numbers/): 在数值对象上部署遍历器 ## Promise对象