ES6 新增了let
命令,用来声明变量,但是所声明的变量,只在let
命令所在的代码块内有效。代码块是{ }所包围的部分,即块级作用域
{{{{{let i = 'Hello World'}}}}}; //五个块级作用域
let有以下几个特性
- 不存在变量提升,即在声明之前使用此变量会报错
let
不允许在相同作用域内,重复声明同一个变量。
const
const
声明一个只读的常量(具备let的特性)。即声明的变量所指向的内存地址不会改变。
global
- 在所有环境下,
global都可以拿到顶层对象
数组解构赋值:从数组中提取值,按照对应位置,即有次序对变量赋值。
let [a, [b], d] = [1, [2, 3], 4];
无论左右形式是否完全匹配,都会把匹配的值赋值,不匹配的忽略(不完全解构)
对象解构赋值
let { foo: baz } = { foo: "aaa", bar: "bbb" };
baz // "aaa"
foo // error: foo is not defined
对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。上面代码中,foo
是匹配的模式,baz
才是变量。真正被赋值的是变量baz
,而不是模式foo
。不完全解构也能实现。
let x;
({x} = {x: 1});//JavaScript 引擎会将{x}
理解成一个代码块,从而发生语法错误。加个圆括号即可解决
字符串解构赋值
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。
const [a, b, c, d, e] = 'hello'; a // "h" b // "e" c // "l" d // "l" e // "o"
//类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。 let {length : len} = 'hello'; len // 5
数值和布尔值的解构赋值
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined
和null
无法转为对象,所以对它们进行解构赋值,都会报错。
函数参数的解构赋值
符合上述解构。
function add([x, y]){ return x + y; } add([1, 2]); // 3
函数add
的参数表面上是一个数组,但在传入参数的那一刻,数组参数就被解构成变量x
和y
。
展开运算符(用三个连续的点 ( ...
) 表示)是 ES6 中的新概念,使你能够将字面量对象展开为多个元素。
const books = ["Don Quixote", "The Hobbit", "Alice in Wonderland", "Tale of Two Cities"];
console.log(...books);
//Don Quixote The Hobbit Alice in Wonderland Tale of Two Cities
剩余参数
剩余参数也用三个连续的点 ( ...
) 表示,使你能够将不定数量的元素表示为数组。
const order = [20.17, 18.67, 1.50, "cheese", "eggs", "milk", "bread"]; const [total, subtotal, tax, ...items] = order; console.log(total, subtotal, tax, items);
//20.17 18.67 1.5 ["cheese", "eggs", "milk", "bread"]
Promise
new Promise(function (resolve, reject) { window.setTimeout(function createSundae(flavor = 'chocolate') { const sundae = {}; // request ice cream // get cone // warm up ice cream scoop // scoop generous portion into cone! resolve(sundae); }, Math.random() * 2000); });
首先Promise 将立即返回一个对象,该对象上具有一个 .then()
方法,我们可以让该方法通知我们 promise 中的请求成功与否。.then()
方法会接收两个函数:
- 请求成功完成时要运行的函数
- 请求失败时要运行的函数
mySundae.then(function(sundae) { console.log(`Time to eat my delicious ${sundae}`); }, function(msg) { console.log(msg); self.goCry(); // not a real method });
Proxy
Proxy 对象介于真正的对象和调用代码之间。调用代码与 Proxy 交互,而不是真正的对象。要创建 Proxy:
- 使用
new Proxy()
构造函数- 将被代理的对象传入为第一项
- 第二个对象是 handler(处理器)对象
- handler 对象由 13 种不同的 trap 之一构成
- trap 是一种函数,将截获对属相的调用,让你运行代码
- 如果未定义 trap,默认行为会被发送给目标对象
Proxy 是一种强大的创建和管理对象之间的交互的新方式。
可暂停的函数
如果我们希望能够中途暂停运行函数,则需要使用 ES6 中新提供的一种函数,叫做 generator(生成器)函数!我们来看一个示例:
function* getEmployee() { console.log('the function has started'); const names = ['Amanda', 'Diego', 'Farrin', 'James', 'Kagure', 'Kavita', 'Orit', 'Richard']; for (const name of names) { console.log( name ); } console.log('the function has ended'); }
注意到 function
关键字后面的星号(即 *
)了吗?星号表示该函数实际上是生成器!生成器被调用时,它不会运行函数中的任何代码,而是创建和返回迭代器。该迭代器可以用来运行实际生成器的内部代码。关键字 yield
是 ES6 中新出现的关键字。只能用在生成器函数中。yield
会导致生成器暂停下来。
function* createSundae() { const toppings = []; toppings.push(yield); toppings.push(yield); toppings.push(yield); return toppings; } var it = createSundae(); it.next('hot fudge');//第一次调用 it.next('sprinkles'); it.next('whipped cream'); it.next();//因为第一次调用.next()
传入了一些数据。但是该数据没有存储在任何位置。最后一次调用.next()
应该会获得一些数据,因为生成到对toppings.push()
的最后一次调用中。
第一次调用 .next()
将初始化生成器,将在第一个 yield
位置暂停。第二次调用.next()
将向该 yield
提供数据。