1.let命令:块级作用域变量
个人认为以下两段代码等价
const fun = Array();
for(let i = 0; i < 10; i++){
fun.push(
function(){
console.log(i);
}
);
}
for(var i = 0; i < 10; i++){
(function(i){
fun.push(
function(){
console.log(i);
}
);
})(i);
}
let命令不存在变量提升,一旦let声明变量则绑定该区域,不能重复声明。
暂时性死区
只要块级作用域内存在let
命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
上面代码中,存在全局变量tmp
,但是块级作用域内let
又声明了一个局部变量tmp
,导致后者绑定这个块级作用域,所以在let
声明变量前,对tmp
赋值会报错。
2.const
const
声明一个只读的常量。一旦声明,常量的值就不能改变。一旦声明变量,就必须立即初始化。
同样是块级作用域,变量声明不提升,不能重复声明,
const
实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。
3.解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
(1)数组解构赋值:事实上,只要某种数据结构具有接口,都可以采用数组形式的解构赋值。
(2)对象解构复制: 对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。例:
let {
foo: baz } = {
foo: 'aaa', bar: 'bbb' };
(3)字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。
const [a, b, c, d, e] = 'hello';
(4)数值和布尔值的解构,赋值解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。
(5)函数的参数也可以使用解构赋值。
function add([x, y]){
return x + y;
}
(6)上面代码的写法会报错,因为 JavaScript 引擎会将{x}
理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。
// 错误的写法
let x;
{
x} = {
x: 1};
// SyntaxError: syntax error
(7)扩展运算符( spread )是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
一行实现数组去重: [...arr] = new Set([1, 2, 3, 2]);
4.字符串拓展
ES5以前,字符串使用UTF-16的子集编码(UCS-2),码元为两个字节,无法识别四个字节的辅助平面字符
ES6解决了辅助平面字符的识别,使用将码点放入大括号,就能正确解读该字符。如'\u{1D306}'
并保持了向后兼容性,故字符串长度仍然以两个字节为单位,如要得到字符串的实际长度应为Array.from('\u{1D306}')
识别 32 位的 UTF-16 字符(Unicode 编号大于0xFFFF
)。
String.fromCharCode(0x20BB7)
// "ஷ"
上面代码中,String.fromCharCode
不能识别大于0xFFFF
的码点,所以0x20BB7
就发生了溢出,最高位2
被舍弃了,最后返回码点U+0BB7
对应的字符,而不是码点U+20BB7
对应的字符。
ES6 提供了String.fromCodePoint
方法,可以识别大于0xFFFF
的字符,弥补了String.fromCharCode
方法的不足。在作用上,正好与codePointAt
方法相反。
5.数值的拓展
ES6 提供了二进制和八进制数值的新的写法,分别用前缀0b
(或0B
)和0o
(或0O
)表示。
如果要将0b
和0o
前缀的字符串数值转为十进制,要使用Number
方法,对parseInt方法无效
ES6 在Number
对象上,新提供了Number.isFinite()
和Number.isNaN()
两个方法。
它们与传统的全局方法