块级作用域绑定
使用var声明
原来我们在js中声明变量是使用var关键字。
我们都知道,使用var声明变量,会有变量提升,比如下面的代码:
1 | console.log(value); //undefined |
通知台会打印undefined,实际JavaScript引擎将代码理解成下面这样:
1 | var value; |
所有的变量的声明都会被提升至函数的顶部。
另一个使用var声明的特点是,var声明的变量作用域是函数作用域。
块级声明
ES6引入了块级声明,具体有let声明和const声明。
let声明的用法与var相同,区别有如下:
- 不会变量提升
用let声明变量,在变量声明之前是不可以使用的,若使用则会报错。
1 | console.log(value); //ReferenceError: value is not defined |
- 块级作用域
用let声明的变量,作用的范围在{}之中,执行流离开{}变量就会销毁。
- 禁止重声明
var重复声明则后面的会覆盖前面的,let重复声明则会报错。
const声明的行为类似于let,但const定义的为常量,不可在使用过程中修改。
但是,有一点要注意,js中的常量如果是对象,则对象的值可以修改。这一点与其他语言中的常量有所不同。
循环中的块作用域
js编程中的一个经典问题如下:
1 | var funcs = []; |
这个问题的原因是js并不像我们想象的那样运行,我们希望每次的i都是独立的i,每次打印当前循环阶段的i。
而实际情况是,所有的i都是共享的,而在循环结束的时候,i的值为10。传入的回调函数作为闭包可以访问i的值,但当调用的时候,i已经变成10了。所以每次调用打印的都是10。
通常解决这个问题我们都是采用立即调用函数表达式(IIFE)。如下:
1 | var funcs = []; |
既丑陋又难以理解。
而使用let在循环中声明变量就简单多了:
1 | var funcs = []; |
这种结果符合我们理解的期望。每次循环的时候let声明都会创建一个新变量i,并将其初始化为i的当前值。
需要注意的是,let声明在循环中的这种行为是专门定义的,与let的不提升特性无关。
而const声明可以在for-in和for-of中使用,但是若在for循环中,出现i++等修改常量的行为则会报错。
字符串
模板字面量
模板字面量是ES6中一个重要的新增特性,主要有下面这些能力:
- 多行字符串
模板字面量可以轻易的创建多行字符串:
1 | let message = `Multiline |
- 字符串占位符
在一个模板字面量中,你可以把任何合法的JavaScript表达式嵌入到占位符中并将其作为字符串的一部分输出到结果中。
1 | let name = "Nicholas", |
还可以嵌入如运算式、函数调用等JavaScript表达式
1 | let count = 10, |
还可以在一个模板字面量里面嵌入另外一个模板字面量
1 | let name = "Nicholas", |
- 标签模板
模板标签可以执行模板字面量上的转换并返回最终的字符串值。等于可以自定义字符串组合的方式。标签指的是在模板字面量第一个反撇号(`)前方标注的字符串。
1 | function passthru(literals,...substitutions){ |