ECMAScript 攻略
3a9cea8df5b14702b262fd7ce3b36311
ECMAScript 攻略
Array#{flat,flatMap}
ECMAScript 2019 在 Array.prototype
上增加了两个方法:flat()
和 flatMap()
。
这两个方法为打平数组提供了便利。如果没有这两个方法,则打平数组就要使用迭代或递归
// 手写实现
/*
数组中每个元素都像一个子节点,非数组元素是叶节点。
因此,这个例子中的输入数组是一个高度为 2 有 7 个叶节点的树。打平这个数组本质上是对叶节点的按
序遍历。
第一个参数:源数组
第二个参数:指定打平到第几级嵌套
第三个参数:新数组
*/
function flatten(sourceArray, depth, flattenedArray = []) {
for (const element of sourceArray) {
if (Array.isArray(element) && depth > 0) {
flatten(element, depth - 1, flattenedArray);
} else {
flattenedArray.push(element);
}
}
return flattenedArray;
}
const arr = [[0], 1, 2, [3, [4, 5]], 6];
console.log(flatten(arr, 1));
// [0, 1, 2, 3, [4, 5], 6]
数组的成员有时还是数组,Array.prototype.flat()
用于将嵌套的数组 “拉平”,变成一维的数组。该方法返回一个新数组,对原数据没有影响。
const arr1 = [0, 1, 2, [3, 4]];
console.log(arr1.flat());
// expected output: [0, 1, 2, 3, 4]
const arr2 = [0, 1, 2, [[[3, 4]]]];
console.log(arr2.flat(2));
// expected output: [0, 1, 2, [3, 4]]
flatMap()
只能展开一层数组。
// 相当于 [[[2]], [[4]], [[6]], [[8]]].flat()
[1, 2, 3, 4].flatMap((x) => [[x * 2]]);
// [[2], [4], [6], [8]]
典型场景: 将包含几句话的数组拆分成单个词组成的新数组
let arr1 = ["it's Sunny in", "", "California"];
arr1.map((x) => x.split(" "));
// [["it's","Sunny","in"],[""],["California"]]
arr1.flatMap((x) => x.split(" "));
// ["it's","Sunny","in", "", "California"]
详细内容参考 ES 入门 - flat
Object.fromEntries
提出背景: 前端使用 Map 结构存储数据,但是调用后端 API 时需要传递普通对象,这时候就可以使用Object.fromEntries()
进行转换
Object.fromEntries
是与 Object.entries()
相反的方法,用于将一个键值对数组转为对象。
Object.fromEntries([
["foo", "bar"],
["baz", 42],
]);
// { foo: "bar", baz: 42 }
该方法的主要目的,是将键值对的数据结构还原为对象,因此特别适合将 Map
结构转为对象。
使用场景:
Map 键值对结构转换为对象
// 例一
const entries = new Map([
["foo", "bar"],
["baz", 42],
]);
Object.fromEntries(entries);
// { foo: "bar", baz: 42 }
// 例二
const map = new Map().set("foo", true).set("bar", false);
Object.fromEntries(map);
// { foo: true, bar: false }
Array 转化为 Object
const arr = [
["0", "a"],
["1", "b"],
["2", "c"],
];
const obj = Object.fromEntries(arr);
console.log(obj); // { 0: "a", 1: "b", 2: "c" }
浏览器查询参数转换为对象
let query = Object.fromEntries(new URLSearchParams("foo=bar&baz=qux"));
// {foo: "bar", baz: "qux"}
console.log(query);
将对象的值重新组合
let arr = [
{ name: "Alice", age: 40 },
{ name: "Bob", age: 36 },
];
let obj = Object.fromEntries(arr.map(({ name, age }) => [name, age]));
// {Alice: 40, Bob: 36}
console.log(obj);
String#{trimStart,trimEnd}
ES2019 对字符串实例新增了trimStart()
和trimEnd()
这两个方法。它们的行为与trim()
一致,
trimStart()
消除字符串头部的空格,trimEnd()
消除尾部的空格。
它们返回的都是新字符串,不会修改原始字符串。
const s = " abc ";
s.trim(); // "abc"
s.trimStart(); // "abc "
s.trimEnd(); // " abc"
复制代码
Symbol#description
创建 Symbol
的时候,可以添加一个描述。
const sym = Symbol("foo");
上面代码中,sym
的描述就是字符串 foo
。
但是,读取这个描述需要将 Symbol
显式转为字符串,即下面的写法。
const sym = Symbol("foo");
String(sym); // "Symbol(foo)"
sym.toString(); // "Symbol(foo)"
上面的用法不是很方便。ES2019 提供了一个实例属性 description
,直接返回 Symbol 的描述。
const sym = Symbol("foo");
sym.description; // "foo"
ES2019 提供了一个实例属性description
,直接返回 Symbol 的描述。
// 创建 Symbol 的时候,可以添加一个描述。
const sym = Symbol("foo");
sym.description; // "foo"
上面代码中,sym
的描述就是字符串 foo
。
try {} catch {} // optional binding
旧版本的try / catch
语句中的catch
子句需要一个变量。 现在可以不加了
// 旧版本
try {
console.log(a);
} catch (error) {
console.log("报错了");
}
// ES2019-SE10
// 如果我们对错误信息漠不关心,只想知道是否报错,就可以忽略catch的参数
try {
console.log(a);
return true;
} catch {
console.log("报错了");
return false;
}
U+2028 和 U+2029
在 ES2019 之前的版本中,不接受不转义的
- 行分隔符
U + 2028
- 段落分隔符
U + 2029
ES2019 允许 JavaScript 字符串直接输入 U+2028(行分隔符)和 U+2029(段分隔符)。
/*
ES2019之前,下面的代码会报错
ES2019 下面代码不会报错。
*/
const PS = eval("'\u2029'");
JSON-stringify - 的改造
为了确保返回的是合法的 UTF-8 字符,ES2019 改变了 JSON.stringify()
的行为。如果遇到 0xD800
到 0xDFFF
之间的单个码点,或者不存在的配对形式,它会返回转义字符串,留给应用自己决定下一步的处理。
JSON.stringify("\u{D834}"); // ""\\uD834""
JSON.stringify("\uDF06\uD834"); // ""\\udf06\\ud834""
Array.prototype.sort() 的稳定排序
早先的 ECMAScript 没有规定,Array.prototype.sort()
的默认排序算法是否稳定,留给浏览器自己决定,这导致某些实现是不稳定的。ES2019 明确规定,Array.prototype.sort()
的默认排序算法必须稳定。这个规定已经做到了,现在 JavaScript 各个主要实现的默认排序算法都是稳定的。
const arr = ["peach", "straw", "apple", "spork"];
const stableSorting = (s1, s2) => {
if (s1[0] < s2[0]) return -1;
return 1;
};
arr.sort(stableSorting);
// ["apple", "peach", "straw", "spork"]
revised Function#toString
ES2019 对函数实例的 toString()
方法做出了修改。
toString()
方法返回函数代码本身,以前会省略注释和空格。
function /* foo comment */ foo() {}
// 老版本
foo.toString();
// function foo() {}
// 新版
foo.toString();
// "function /* foo comment */ foo () {}"
- Array#{flat,flatMap}
- Object.fromEntries
- Map 键值对结构转换为对象
- Array 转化为 Object
- 浏览器查询参数转换为对象
- 将对象的值重新组合
- String#{trimStart,trimEnd}
- Symbol#description
- try {} catch {} // optional binding
- U+2028 和 U+2029
- JSON-stringify - 的改造
- Array.prototype.sort() 的稳定排序
- revised Function#toString