ES8系列目录
- 1 async函数
- 2 Promise.prototype.finally()
- 3 Object.values(),Object.entries()
- 4 Object.getOwnPropertyDescriptors()
- 5 字符串填充 padStart和padEnd
- 6 函数参数列表与调用中的尾部逗号
- 7 共享内存与原子操作
所有整理的文章都收录到我《Cute-JavaScript》系列文章中,访问地址:http://js.pingan8787.com
3 Object.values(),Object.entries()
ES7中新增加的 Object.values()
和 Object.entries()
与之前的 Object.keys()
类似,返回数组类型。
回顾下 Object.keys()
:
-
var a = { f1: 'hi', f2: 'leo'};
-
Object.keys(a); // ['f1', 'f2']
3.1 Object.values()
返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历属性的键值。
-
let a = { f1: 'hi', f2: 'leo'};
-
Object.values(a); // ['hi', 'leo']
如果参数不是对象,则返回空数组:
-
Object.values(10); // []
-
Object.values(true); // []
3.2 Object.entries()
返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历属性的键值对数组。
-
let a = { f1: 'hi', f2: 'leo'};
-
Object.entries(a); // [['f1','hi'], ['f2', 'leo']]
- 用途1:
遍历对象属性。
-
let a = { f1: 'hi', f2: 'leo'};
-
for (let [k, v] of Object.entries(a)){
-
console.log(
-
`${JSON.stringfy(k)}:${JSON.stringfy(v)}`
-
)
-
}
-
// 'f1':'hi'
-
// 'f2':'leo'
- 用途2: 将对象转为真正的Map结构。
-
let a = { f1: 'hi', f2: 'leo'};
-
let map = new Map(Object.entries(a));
手动实现 Object.entries()
方法:
-
// Generator函数实现:
-
function* entries(obj){
-
for (let k of Object.keys(obj)){
-
yield [k ,obj[k]];
-
}
-
}
-
// 非Generator函数实现:
-
function entries (obj){
-
let arr = [];
-
for(let k of Object.keys(obj)){
-
arr.push([k, obj[k]]);
-
}
-
return arr;
-
}
4 Object.getOwnPropertyDescriptors()
之前有 Object.getOwnPropertyDescriptor
方法会返回某个对象属性的描述对象,新增的 Object.getOwnPropertyDescriptors()
方法,返回指定对象所有自身属性(非继承属性)的描述对象,所有原对象的属性名都是该对象的属性名,对应的属性值就是该属性的描述对象
-
let a = {
-
a1:1,
-
get f1(){ return 100}
-
}
-
Object.getOwnPropetyDescriptors(a);
-
/*
-
{
-
a:{ configurable:true, enumerable:true, value:1, writeable:true}
-
f1:{ configurable:true, enumerable:true, get:f, set:undefined}
-
}
-
*/
实现原理:
-
function getOwnPropertyDescriptors(obj) {
-
const result = {};
-
for (let key of Reflect.ownKeys(obj)) {
-
result[key] = Object.getOwnPropertyDescriptor(obj, key);
-
}
-
return result;
-
}
引入这个方法,主要是为了解决 Object.assign()
无法正确拷贝 get
属性和 set
属性的问题。
-
let a = {
-
set f(v){
-
console.log(v)
-
}
-
}
-
let b = {};
-
Object.assign(b, a);
-
Object.a(b, 'f');
-
/*
-
f = {
-
configurable: true,
-
enumable: true,
-
value: undefined,
-
writeable: true
-
}
-
*/
value
为 undefined
是因为 Object.assign
方法不会拷贝其中的 get
和 set
方法,使用 getOwnPropertyDescriptors
配合 Object.defineProperties
方法来实现正确的拷贝:
-
let a = {
-
set f(v){
-
console.log(v)
-
}
-
}
-
let b = {};
-
Object.defineProperties(b, Object.getOwnPropertyDescriptors(a));
-
Object.getOwnPropertyDescriptor(b, 'f')
-
/*
-
configurable: true,
-
enumable: true,
-
get: undefined,
-
set: function(){...}
-
*/
Object.getOwnPropertyDescriptors
方法的配合 Object.create
方法,将对象属性克隆到一个新对象,实现浅拷贝。
-
const clone = Object.create(Object.getPrototypeOf(obj),
-
Object.getOwnPropertyDescriptors(obj));
-
// 或者
-
const shallowClone = (obj) => Object.create(
-
Object.getPrototypeOf(obj),
-
Object.getOwnPropertyDescriptors(obj)
-
);
5 字符串填充 padStart和padEnd
用来为字符串填充特定字符串,并且都有两个参数:字符串目标长度和填充字段,第二个参数可选,默认空格。
-
'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'
从上面结果来看,填充函数只有在字符长度小于目标长度时才有效,若字符长度已经等于或小于目标长度时,填充字符不会起作用,而且目标长度如果小于字符串本身长度时,字符串也不会做截断处理,只会原样输出。
6 函数参数列表与调用中的尾部逗号
该特性允许我们在定义或者调用函数时添加尾部逗号而不报错:
-
function es8(var1, var2, var3,) {
-
// ...
-
}
-
es8(10, 20, 30,);
7 共享内存与原子操作
当内存被共享时,多个线程可以并发读、写内存中相同的数据。原子操作可以确保那些被读、写的值都是可预期的,即新的事务是在旧的事务结束之后启动的,旧的事务在结束之前并不会被中断。这部分主要介绍了 ES8 中新的构造函数 SharedArrayBuffer
以及拥有许多静态方法的命名空间对象 Atomic
。
Atomic
对象类似于 Math
对象,拥有许多静态方法,所以我们不能把它当做构造函数。 Atomic
对象有如下常用的静态方法:
- add /sub :为某个指定的value值在某个特定的位置增加或者减去某个值
- and / or /xor :进行位操作
- load :获取特定位置的值