ES2017 中对 Javascript 的新增和改进
字符串填充 String padding
String 增加了两个实例方法 — padStart 和 padEnd,这两个方法可以在字符串的首/尾添加其他字符串,类似数组的 unshift,push 方法
语法
str.padStart(targetLength [, padString])
str.padEnd(targetLength [, padString])
参数
- targetLength
当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。
- padString 可选
填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧/右侧的部分,其他部分会被截断。此参数的默认值为 " "(U+0020)。
例子
"es8".padStart(2); // 'es8'
"es8".padStart(5); // ' es8'
"es8".padStart(6, "woof"); // 'wooes8'
"es8".padStart(14, "wow"); // 'wowwowwowwoes8'
"es8".padStart(7, "0"); // '0000es8'
"es8".padEnd(2); // 'es8'
"es8".padEnd(5); // 'es8 '
"es8".padEnd(6, "woof"); // 'es8woo'
"es8".padEnd(14, "wow"); // 'es8wowwowwowwo'
"es8".padEnd(7, "6"); // 'es86666'
对象值遍历 Object.values
Object.values 函数会返回指定对象的可枚举的属性值数组,数组中值顺序与 for-in 循环保持一致,函数的声明为:
Object.values(obj);
首个参数 obj 即为需要遍历的目标对象,它可以为某个对象或者数组(数组可以看做键为下标的对象):
const obj = { x: "xxx", y: 1 };
Object.values(obj); // ['xxx', 1]
const obj = ["e", "s", "8"]; // same as { 0: 'e', 1: 's', 2: '8' };
Object.values(obj); // ['e', 's', '8']
// 当使用数字作为key时,返回的值的顺序是和key的大小顺序一致的
const obj = { 10: "xxx", 1: "yyy", 3: "zzz" };
Object.values(obj); // ['yyy', 'zzz', 'xxx']
Object.values("es8"); // ['e', 's', '8']
对象键和值的遍历 Object.entries
Object.keys 和 Object.values 的结合体,方法返回一个给定对象自身可枚举属性的键值对数组,数组中顺序与 Object.values 保持一致,数组的每一项为[key, value]
const obj = { x: "xxx", y: 1 };
Object.entries(obj); // [['x', 'xxx'], ['y', 1]]
const obj = ["e", "s", "8"];
Object.entries(obj); // [['0', 'e'], ['1', 's'], ['2', '8']]
const obj = { 10: "xxx", 1: "yyy", 3: "zzz" };
Object.entries(obj); // [['1', 'yyy'], ['3', 'zzz'], ['10': 'xxx']]
Object.entries("es8"); // [['0', 'e'], ['1', 's'], ['2', '8']]
获取对象的属性描述符 Object.getOwnPropertyDescriptors, Object.getOwnPropertyDescriptor
getOwnPropertyDescriptors 函数会返回指定对象的某个指定属性的描述符;该属性必须是对象自己定义而不是继承自原型链,函数的声明为:
Object.getOwnPropertyDescriptor(obj, prop);
Object.getOwnPropertyDescriptors(obj);
obj 即为源对象,而 prop 即为需要查看的属性名;结果中包含的键可能有 configurable、enumerable、writable、get、set 以及 value。
const obj = {
get es8() {
return 888;
},
};
Object.getOwnPropertyDescriptor(obj, "es8");
// {
// configurable: true,
// enumerable: true,
// get: function es8(){}, //the getter function
// set: undefined
// }
const objj = {
a: 1,
b: "2",
c: true,
d: null,
e: undefined,
f: {},
};
Object.getOwnPropertyDescriptors(objj);
// {
// a: {value: 1, writable: true, enumerable: true, configurable: true},
// b: {value: "2", writable: true, enumerable: true, configurable: true},
// c: {value: true, writable: true, enumerable: true, configurable: true},
// d: {value: null, writable: true, enumerable: true, configurable: true},
// e: {value: undefined, writable: true, enumerable: true, configurable: true},
// f: {value: {}, writable: true, enumerable: true, configurable: true},
// }
函数参数列表与调用中的尾部逗号 Trailing commas in function
JavaScript 一开始就支持数组字面值中的尾后逗号,随后向对象字面值(ECMAScript 5)中添加了尾后逗号。
ES8 标准中允许函数参数列表与调用中的尾部逗号,该特性允许我们在定义或者调用函数时添加尾部逗号。
但是 JSON 不支持尾后逗号。
function es8(var1, var2, var3) {
// do something
//函数内部的 arguments.length 是 3 还是 4 ?
console.log(arguments.length); // 3
}
es8(10, 20, 30);
异步函数 Async function
async 函数是使用 async 关键字声明的函数。 async 函数是 AsyncFunction 构造函数的实例, 并且其中允许使用 await 关键字。async 和 await 关键字让我们可以用一种更简洁的方式写出基于 Promise 的异步行为,而无需刻意地链式调用 promise。
ES8 中允许使用 async/await 语法来定义与执行异步函数,async 关键字会返回某个 AsyncFunction 对象;在内部实现中虽然异步函数与迭代器的实现原理类似,但是其并不会被转化为迭代器函数:
function resolveAfter2Seconds() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("resolved");
}, 2000);
});
}
async function asyncCall() {
console.log("calling");
const result = await resolveAfter2Seconds();
console.log(result);
}
asyncCall();
// calling
// resolved
共享内存与原子操作 SharedArrayBuffer, Atomics
- SharedArrayBuffer
SharedArrayBuffer 对象用来表示一个通用的,固定长度的原始二进制数据缓冲区,类似于 ArrayBuffer 对象,它们都可以用来在共享内存(shared memory)上创建视图。与 ArrayBuffer 不同的是,SharedArrayBuffer 不能被分离。
共享内存能被同时创建和更新于工作者线程或主线程。依赖于系统(CPU,操作系统,浏览器),变化传递给环境需要一段时间。需要通过 atomic 操作来进行同步。
- Atomics
Atomics 对象提供了一组静态方法用来对 SharedArrayBuffer 对象进行原子操作。
这些原子操作属于 Atomics 模块。与一般的全局对象不同,Atomics 不是构造函数,因此不能使用 new 操作符调用,也不能将其当作函数直接调用。Atomics 的所有属性和方法都是静态的(与 Math 对象一样)。
多个共享内存的线程能够同时读写同一位置上的数据。原子操作会确保正在读或写的数据的值是符合预期的,即下一个原子操作一定会在上一个原子操作结束后才会开始,其操作过程不会中断。