这份文档整理了博主在前端项目中经常需要查阅ES6+的代码,并作出相应解释以及给出最新的代码示例。除此之外,博主还会偶尔会写上一些我的小技巧,也会注意提示这只是我的个人提议。
你或许会因为不熟悉当前一些新的代码库(例如 React)所用到的 JavaScript 概念,而很难上手这些新框架。所以本文档的目的并非从零教你 JavaScript,而是帮助已经有一定编程基础的你。
注:这篇文档里提到的大多数概念来自于目前最新的 JavaScript(ES2015,即 ES6),你可以在 这里 查看新增的特性,网站做得很棒。
常用语法
- 变量声明
let // 块级作用域变量声明 代替了var声明 const // 常量声明 在开发中一般不让修改的值使用const声明
- 解构赋值
// 结构赋值可以用于数组 也可以用于对象 let [a, b, c] = [1, 2, 3]; let [head, ...tail] = [1, 2, 3, 4]; // tail === [2,3,4] let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
- 扩展运算符
// 可以将一个数组的元素放入到另一个数组 组成一个新的数组 并且地址引用不同 一般用于创建的数据 解决地址引用问题 const arr = [1,2,3]; const brr = [6, ...arr];
- 模版字符串
// 可以在字符串中正常使用变量 const name = '憧憬'; let str = `你好${name}!`;
- 箭头函数
// 新的函数声明方式 可以解决this指向问题。默认绑定上下文this const f = () => { }
- 函数多参数传递 rest参数
function add(...values) { // 不使用传统的arguments对象 // values === [1,2,3] } add(1,2,3);
- 将对象转为数组 Array.from()
let arrayLike = { '0': 'a', '1': 'b', '2': 'c', length: 3 }; Array.from(arrayLike); // ['a', 'b', 'c']
- 判断数组是否包含给定值 includes
[1, 2, 3].includes(2) // true
- 数组维度转换 flat
//转一维 [1, 2, [3, 4]].flat() // [1, 2, 3, 4]
- 获取对象的原型对象 super
const proto = { foo: 'hello' }; const obj = { foo: 'world', find() { return super.foo; } }; Object.setPrototypeOf(obj, proto); obj.find() // "hello"
- 链式判断运算符 很常用
const firstName = (message && message.body && message.body.user && message.body.user.firstName) || 'default'; const firstName = message?.body?.user?.firstName || 'default'; // 上面代码使用了?.运算符,直接在链式调用的时候判断,左侧的对象是否为null或undefined。如果是的,就不再往下运算,而是返回undefined。 a?.b // 等同于 a == null ? undefined : a.b
- Null 判断运算符 ?? 很常用
// 以前 const headerText = response.settings.headerText || 'Hello, world!'; // 现在 const headerText = response.settings.headerText ?? 'Hello, world!';
- 对象合并 Object.assign
// 解决同一对象地址引用问题 如果键相同 后者覆盖前者 const target = { a: 1 }; const source1 = { b: 2 }; const source2 = { c: 3 }; Object.assign(target, source1, source2); target // {a:1, b:2, c:3}
- set操作
// 主要集合操作 去重 const set = new Set([1, 2, 3, 4, 4]); set.add(); // 添加某个值,返回 Set 结构本身。 set.delete(); // 删除某个值,返回一个布尔值,表示删除是否成功。 set.has(); // 返回一个布尔值,表示该值是否为Set的成员。 set.clear(); // 清除所有成员,没有返回值。 set.size // 获取set的成员数量
- map操作
// 对 对象的扩展 对象以前键是不能使用对象的 const m = new Map(); const map = new Map(); map.set('foo', true); // 写入值到map里面 map.size // 获取map成员数量 map.get('key') // 获取map成员值 map.has('key'); map.delete('key'); map.clear();
高阶函数
- map 对数组的每一个成员进行遍历, 并将返回值 组成一个新的数组
const arr = [1,2,3]; const brr = arr.map((item) => { return item*2; }); // brr === [2,4,6]
- filter 对数组进行遍历 给定条件 条件为真保留 否则去掉 返回一个新的数组
const arr = [1,2,3]; const brr = arr.filter((item) => { return item > 1; }); // brr === [2,3]
- reduce 用于函数的 compose
// item为初始值, [[]], 循环每次返回值都会作为下一次的item // val为当前循环的值 // index为当前循环的索引 // brr为循环的数组 const arr = [1,2,3,4]; arr.reduce((item, val, index, brr) => { item[0].push(val); return item; }, [[]]);
- forEach 只是对数组进行遍历
arr.forEach((item) => { console.log("aoppp.com"); });
- every 对数组中每一项运行给定函数,如果该函数对每一项返回true,则返回true。
const arr = [ 1, 2, 3, 4, 5, 6 ]; arr.some((item, index, array) => { return item > 3; })); // false
- some 对数组中每一项运行给定函数,如果该函数对任一项返回true,则返回true。
const arr = [ 1, 2, 3, 4, 5, 6 ]; arr.some((item, index, array) => { return item > 3; })); // true
- find
// 找出第一个符合条件的数组成员 [1, 5, 10, 15].find(function(value, index, arr) { return value > 9; }) // 10
- findIndex
// 数组实例的findIndex方法的用法与find方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。 [1, 5, 10, 15].findIndex(function(value, index, arr) { return value > 9; }) // 2
- Promise 异步操作
const promise = new Promise(function(resolve, reject) { // ... some code if (/* 异步操作成功 */){ resolve(value); } else { reject(error); } }); promise.then((res) => { // 可以获取到promise resolve的值 }).catch(() => { // 可以获取 promise reject的值 }).finally(() => { // 每次都会执行这个 });
- Promise.all() 多个异步
// 执行多个promise操作 Promise.all([p1, p2, p3]); // (1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。 // (2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
- Promise.race() 多个异步操作 谁先返回获取谁
const p = Promise.race([p1, p2, p3]); // 上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
- Promise.allSettled 多个异步 强制等待
const promises = [ fetch('/api-1'), fetch('/api-2'), fetch('/api-3'), ]; // Promise.allSettled()方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果,不管是fulfilled还是rejected,包装实例才会结束
- Async + await 多个异步变同步
const asyncReadFile = async function () { const f1 = await readFile('/etc/fstab'); // 利用await就可以将异步 变成同步的 const f2 = await readFile('/etc/shells'); console.log(f1.toString()); console.log(f2.toString()); };
- export + import 模块导入导出
// ./profile.js const firstName = 'Michael'; const lastName = 'Jackson'; const year = 1958; export { firstName, lastName, year }; // main.js import { firstName as newName, lastName, year } from './profile.js'; // 导入时还可以利用as起别名 避免变量冲突 // 从前面的例子可以看出,使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。 // 默认导出 export-default.js export default function () { console.log('foo'); } // import-default.js import customName from './export-default'; customName(); // 'foo'
本文为作者原创,手码不易,允许转载,转载后请以链接形式说明文章出处。