最全 ECMAScript 攻略之 ES2017-ES8

Object.values/Object.entries

直接获取对象的值是一种非常常见的用例-例如,在将对象用作哈希过滤器时。许多库都有一个“值”函数:lodash 的mapValues

Object.values 方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。

const obj = { foo: "bar", baz: 42 };
Object.values(obj);
// ["bar", 42]

const obj = { 100: "a", 2: "b", 7: "c" };
Object.values(obj);
// ["b", "c", "a"]
复制代码

Object.entries方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。

const obj = { foo: "bar", baz: 42 };
Object.entries(obj);
// [ ["foo", "bar"], ["baz", 42] ]
复制代码

Object.entries 的基本用途是

Object.entries 遍历对象的属性

let obj = { one: 1, two: 2 };
for (let [k, v] of Object.entries(obj)) {
  console.log(`${JSON.stringify(k)}: ${JSON.stringify(v)}`);
}
// "one": 1
// "two": 2
复制代码

Object.entries 将对象转为真正的 Map 结构。

const obj = { foo: "bar", baz: 42 };
const map = new Map(Object.entries(obj));
map; // Map { foo: "bar", baz: 42 }
复制代码

String padding

ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。

第一个参数是需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。

第二个参数是需要填充的字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断。此参数的默认值为 ” “(U+0020)。

"x".padStart(5, "ab"); // 'ababx'
"x".padStart(4, "ab"); // 'abax'

"x".padEnd(5, "ab"); // 'xabab'
"x".padEnd(4, "ab"); // 'xaba'
复制代码

padStart()的常见用途是为数值补全指定位数。下面代码生成 10 位的数值字符串。

"1".padStart(10, "0"); // "0000000001"
"12".padStart(10, "0"); // "0000000012"
"123456".padStart(10, "0"); // "0000123456"
复制代码

另一个用途是提示字符串格式。

"12".padStart(10, "YYYY-MM-DD"); // "YYYY-MM-12"
"09-12".padStart(10, "YYYY-MM-DD"); // "YYYY-09-12"
复制代码

Object.getOwnPropertyDescriptors

ES2017 引入了 Object.getOwnPropertyDescriptors()方法,返回指定对象所有自身属性(非继承属性)的描述对象

  • value — 属性实际的值
  • writable — 属性的值是否可以被修改
  • get — 获取函数,在读取属性时调用
  • set — 设置函数,在写入属性时调用
  • configurable — 属性是否可以通过 delete 删除并重新定义,是否可以修改它的特 性,以及是否可以把它改为访问器属性
  • enumerable — 属性是否可以通过 for-in 循环返回

该方法的引入目的,主要是为了解决 Object.assign()无法正确拷贝 get 属性和 set 属性的问题。

const obj = {
  getData: () => {
    return "a";
  },
  get getData() {
    return "b";
  },
  set setDate(n) {
    return "c";
  },
  name: "name",
};

const a = Object.assign(obj);
// index.html:29 Uncaught TypeError: a.getData is not a function
console.log(a.getData());

// -----------------------------

const source = {
  set foo(value) {
    console.log(value);
  },
};

const target1 = {};
Object.assign(target1, source);

Object.getOwnPropertyDescriptors(target1, "foo");
// { value: undefined,
//   writable: true,
//   enumerable: true,
//   configurable: true }
复制代码

上面代码中,source 对象的 foo 属性的值是一个赋值函数,Object.assign 方法将这个属性拷贝给 target1 对象,结果该属性的值变成了 undefined。这是因为 Object.assign 方法总是拷贝一个属性的值,而不会拷贝它背后的赋值方法或取值方法。

Object.getOwnPropertyDescriptors()方法的另一个用处,是配合 Object.create()方法,将对象属性克隆到一个新对象。这属于浅拷贝。

const shallowClone = (object) =>
  // 创建一个新对象
  Object.create(
    // 返回指定对象的原型
    Object.getPrototypeOf(object),
    // 返回指定对象所有自身属性
    Object.getOwnPropertyDescriptors(object),
  );
// 或者
const shallowMerge = (target, source) =>
  Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
复制代码

更多详细内容参考ES 入门教程-getOwnPropertyDescriptors

函数参数的尾逗号

ES2017 允许函数的最后一个参数有尾逗号(trailing comma)。

此前,函数定义和调用时,都不允许最后一个参数后面出现逗号。

function clownsEverywhere(param1, param2) {
  /* ... */
}

clownsEverywhere("foo", "bar");
复制代码

更多详细内容参考ES 入门教程-函数参数的尾逗号

异步函数(Async functions)

ES2017 标准引入了 async 函数,使得异步操作变得更加方便。

async 函数是什么?一句话,它就是 Generator 函数的语法糖。

function fakeRequest() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("请求成功");
    }, 2000);
  });
}

async function getData() {
  console.log("start");
  const res = await fakeRequest();
  console.log(res);
  console.log("end");
}
getData();
/*
1.start
2.请求成功
3.end
*/
复制代码

使用 Atomics 共享内存

Atomics 对象提供了一组静态方法对 SharedArrayBufferArrayBuffer 对象进行原子操作。

更多详细内容参考MDN-Atomics


最后

文章浅陋,欢迎各位看官评论区留下的你的见解!

觉得有收获的同学欢迎点赞,关注一波!

good

往期文章

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享