Skip to content

ECMAScript 6

ECMAScript 6.0 是 2015 年 6 月年发布的新的 JavaScript 语言标准,它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。下面介绍 ECMAScript 6 一些主要新增的特性。

变量声明

const 用于声明常量,let 用于声明变量,他们都是块级作用域。

const a = 1;
let b = 1;

模板字符串

用于拼接字符串。

let a = 'hello';
let b = 'hello';
console.log('print:' + a + b);
let c = `print:${a}${b}`

默认参数

function test(a = 'world') {
console.log(`print:hello,${a}`);
}
test();
// print:hello,world

箭头函数

函数的简化写法。

function test(a = 'world') {
console.log(`print:hello,${a}`);
}
const test = (a = 'world') => {
console.log(`print:hello,${a}`);
};

模块的导入和导出

import { Button } from 'antd';
// 导出一个方法,这样就能在其他文件使用 `import` 导入使用了
const test = (a = 'world') => {
console.log(`print:hello,${a}`);
};
export default test;

析构赋值

const obj = { key: 'umi', author: 'sorrycc' };
console.log(obj.key);
const { key } = obj;
// 等价于 `const key = obj.key;`
const obj2 = { key };
// 等价于 `const obj2 = { key: key };`;
// 数组也有类似的用法
const arr = [1, 2];
const [foo, bar] = arr;
console.log(foo);
// 1

展开运算符

用于数组组装:

const arr = ['umi'];
const texts = [...arr, 'dva'];
// texts => ['umi', 'dva']
用于取出数组部分属性:
const arr = ['umi', 'dva', 'antd'];
const [umi, ...other] = arr;
// 前面已经提过析构赋值,所以第一项会赋值给 `umi`,剩下的会被组合成一个 `other` 数组
console.log(umi);
// umi
console.log(other);
// (2)['dva', 'antd']
用于组合新的对象,key 相同时,靠后展开的值会覆盖靠前的值:
const obj = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const obj3 = { ...obj, ...obj2 };
// obj3 => { a: 1, b: 3, c: 4 }

Promise

回调函数 callback

A callback is a function that is passed as an argument to another function and is executed after its parent function has completed.

在 JavaScript 中,回调函数具体的定义为:函数 A 作为参数(函数引用)传递到另一个函数 B 中,并且函数 B 运行完成后再执行函数 A。我们就把函数 A 叫做回调函数。例如:

// 当参数 a 大于 10 且参数 func2 是一个方法时 执行 func2
function func1(a, func2) {
if (a > 10 && typeof func2 == 'function') {
func2()
}
}
func1(11, function() {
console.log('this is a callback')
})
function doSomething(msg, callback) {
alert(msg);
if (typeof callback == "function")
callback();
}
doSomething("存 5000 块", function () {
alert("稍等,马上办理");
alert('2 分钟后,您的业务已办理完毕');
});

回调与同步、异步并没有直接的联系,回调只是一种实现方式,既可以有同步回调,也可以有异步回调。

回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用,用于对该事件或条件进行响应。

回调本质上是一种设计模式。设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。

在 1994 年,由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人合著出版了一本名为 Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素) 的书,该书首次提到了软件开发中设计模式的概念。

四位作者合称 GOF(四人帮,全拼 Gang of Four)。他们所提出的设计模式主要是基于以下的面向对象设计原则。

  • 对接口编程而不是对实现编程。
  • 优先使用对象组合而不是继承。

同步与异步

同步 (Synchronous) 和异步 (Asynchronous) 用来形容一次函数调用时的时间序列。

  • 同步函数调用一旦开始,调用者必须等到函数调用返回后,才能继续后续的行为。
  • 异步函数调用更像一个消息传递,一旦开始,函数调用就会立即返回,调用者就可以继续后续的操作。而异步函数通常会在另外一个线程中,“真实”地执行着。整个过程,不会阻碍调用者的工作。

为什么使用 promise

一般来说我们会碰到的回调嵌套都不会很多,一般就一到两级,但是某些情况下,回调嵌套很多时,代码就会非常繁琐,会给我们的编程带来很多的麻烦,难以维护和调试,一旦出现 bug,牵一发而动全身,这种情况俗称回调地狱。例如:

loadImg('a.jpg', function() {
loadImg('b.jpg', function() {
loadImg('c.jpg', function() {
//...
});
});
});

当异步的任务很多的时候,维护大量的 callback 将是一场灾难。而 Promise 则可以让我们通过链式调用的方法去解决回调嵌套的问题,使我们的代码更容易理解和维护,而且 Promise 还增加了许多有用的特性,让我们处理异步编程得心应手。

Promise 对象

Promise 对象是一个代理对象(代理一个值),被代理的值在 Promise 对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的 promise 对象。

一个 Promise 有以下几种状态:

  1. pending: 初始状态,既不是成功,也不是失败状态。
  2. fulfilled: 意味着操作成功完成。
  3. rejected: 意味着操作失败。
let p = new Promise((resolve, reject) => {
setTimeout(() => {
Math.random() > 0.5 ? resolve('success') : reject('fail');
}, 1000)
});
console.log(p);
p.then((result) => {
console.log(result);
}, (err) => {
console.log(err);
});
  1. 因为 Promise 是一个构造函数,所以我们使用了 new 操作符来创建 promise
  2. 构造函数 Promise 的参数是一个函数(暂时叫它 func),这个函数(func)有两个参数 resolvereject,它们分别是两个函数,这两个函数的作用就是将 promise 的状态从 pending(等待)转换为 resolved(已解决)或者从 pending(等待)转换为 rejected(已失败)。
  3. 创建后的 promise 有一些方法,thencatch。当然我们也可以人为的在 Promise 函数上添加一些满足我们自己需求的方法,方便每一个 promise 对象使用。
  4. then() 方法返回一个 Promise。它最多需要有两个参数:Promise 成功和失败情况的回调函数。
  5. Promise 函数体的内部包裹着一个异步的请求或者操作或者函数;然后我们可以在这个异步的操作完成的时候使用 resolve 函数将我们获得的结果传递出去,或者使用 reject 函数将错误的消息传递出去。
  6. 每个操作都返回一样的 promise 对象,保证链式操作。
  7. 每个链式都通过 then 方法。
  8. 每个操作内部允许犯错,出了错误,统一由 catch error 处理。
  9. 操作内部,也可以是一个操作链,通过 rejectresolve 再造流程。

参考资料

  1. https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise
  2. https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/then