这份文档整理了博主在前端项目中经常需要查阅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'
本文为作者原创,手码不易,允许转载,转载后请以链接形式说明文章出处。