ES7、ES8 更新点梳理

ES7 和 ES8 出来的时间已经蛮长了,对于浏览器的支持也比较好,正巧昨天在调研如何优化 web-worker 的时候看到了一个新特性,顺便与大家分享一下,大佬勿喷

ES7

在 ES7 中,只新增了数组的 includes 和简写的位运算符,我来给大家举个例子吧

1.Array.prototype.includes(value, formIndex)

  • 该方法确定确定某一个值是否存在于当前数组中
参数
  • value: 需要查找的值

  • formIndex: 从指定位置开始查找

返回值
  • 返回值是一个 Boolean 值,true 代表包含,false 代表不包含
const arr = [1, 2, 3, NaN]

// 最简单使用

console.log(arr.includes(2)) // 返回 true
console.log(arr.includes(5)) // 返回 false
console.log(arr.includes(NaN)) // 返回 true

// 当我们知道查询的值大概范围时 (吐槽一下:一直觉得这个参数鸡肋的一批)

// formIndex > 数组长度
console.log(arr.includes(2,5)) // 返回 false

// formIndex < 0
console.log(arr.includes(2, -1)) // 返回 false
console.log(arr.includes(2, -3)) // 返回 true

注:这个地方有一个它内置的计算公示: arr.length + formIndex <= arr.length 如果上述条件满足,将从计算后的位置查询当前值,不满足的话,会从整个数组中查询

2.指数运算简写 **

  • 原来我们在计算 2 的 10 次方时,写法一般都是这样的
const num1 = Math.pow(2, 10)
  • 那其实我们现在可以这样去写
const num2 = 2 ** 10

// 验证一下是否相等
console.log(num1 === num2) // 返回 true
  • 这样去写的话,是不是又可以少写几个字母了~~

ES8

ES8 中我们现在用的最多的首当其冲是 async/await 了,那其实还有很多有意思的东西,我们可以看看

1.async/await

我们分开介绍吧

  • async 这个关键字可以将一个 function 声明成为一个异步方法,返回值是一个 Promise
async function getNumber(num) {
  return num + 10
}
// 同样的方法可以写成这样
const getNumber = async (num) => {
    return num + 10
}
console.log(getNumber(10)) // 返回 Promise {: 20}

  • 如果返回值是一个 promise 的话,我们其实获取值也可以这样写
getNumber(10).then(res => console.log(res))
  • await 这个关键字和 async 一起使用的时候就体现出了优势。该关键字只能在 异步函数 中才会起作用
function promiseFn() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve("result");
    }, 1500);
  });
}
async function fn() {
  let res = await promiseFn();
  console.log("异步代码执行完毕", res);
}
fn(); // wait 1.5s 后,打印 异步代码执行完毕, result

注:多个异步方法需要同时执行,可以使用 await Promise.all[promise1,promise2]

2.Object.values() 和 Object.entries()

  • Object.values() 方法返回一个给定对象自身所有的 key,其中是不包含继承来的 key

  • Object.entries() 方法返回一个数组,包含当前Object中自身所有键值对,同样不包含继承来的值

const obj = { name: 'tal', age: 17 };

console.log(Object.values(obj)); //返回 ['tal', 17]

console.log(Object.entries(obj)); //返回  [['name', 'tal'],['age', 17]]

// 其实对于我们平常开发来说,还是提高了一些效率的
// 例如:遍历对象的键值
Object.entries(obj).forEach(([key, value]) => {
  console.log(`${key}-${value}`);
});


// 如果传入的是字符串会怎样
Object.values('tal') //返回 ["t", "a", "l"]
Object.entries('tal') // 返回 [['0': 't'], ['1': 'a'], ['2': 'l']]

注: 在使用这两个属性时,会发生一个隐式的类型转化,将我们传入的值转为 Object 后,再执行方法

3.String padding

String 新增了两个实例函数 String.prototype.padStartString.prototype.padEnd ,允许将空字符串或其他字符串添加到原始字符串的开头或结尾。

参数
  • targetLength: 当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。
  • padString: (可选)填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断,此参数的缺省值为 ' '。
// 简单写法
console.log('0.0'.padStart(4,'10')) //返回 10.0
console.log('0.0'.padEnd(4,'0')) //返回 0.00 
   
console.log('0.0'.padStart(20)) //返回 0.00    
console.log('0.0'.padEnd(10,'0')) //返回 0.00000000

4.结尾支持逗号

这个功能其实对于我们来说还是比较友好的

例如:一个方法或者对象,我们只是增加了一个属性或者参数,我们需要在最末尾先增加一个逗号后再添加新属性或者参数,这样的话,在 git 上就会出现两行改动,不是很友好

function fn(
    para1: number,
    para: number,
){
    console.log(para1,para);
}
fn(1,2);

let obj = {
    n:'',
    n:'',
}

在支持这样的语法后,我们就可以改一下我们的格式化工具了,避免了提交中会多出的一些改动

5.Object.getOwnPropertyDescriptors()

该函数函数用来获取一个对象的所有自身属性的描述符,如果没有任何自身属性,则返回空对象。

const obj = {
  name: "tal",
  get fn() {
    return "fn";
  }
};

const obj1 = {}
console.log(Object.getOwnPropertyDescriptors(obj1))
console.log(Object.getOwnPropertyDescriptors(obj))
  1. SharedArrayBuffer 与 Atomics

整个梳理了一遍 ES7 和 ES8 的东西后,终于开始聊重头戏了,在用 web-worker 的老师们,可以看看这个东西是不是正好满足了你当前的需求

是不是还在为 worker 线程不能直接获取到主线程的变量而苦恼
是不是还在频繁的使用 postMessage 而感到繁琐
尝试一下 SharedArrayBuffer 吧(好像一段广告词...)

直接上代码

// 这里是主进程代码
// 创建一个worker进程
const worker = new Worker("./worker.js");

// 新建1kb内存
const sharedBuffer = new SharedArrayBuffer(1024);

//  建视图
const intArrBuffer = new Int32Array(sharedBuffer);

for (let i = 0; i < intArrBuffer.length; i++) {
  intArrBuffer[i] = i;
}
// console.log(sharedBuffer);
// postMessage  发送的共享内存地址
worker.postMessage(intArrBuffer);

worker.onmessage = function(e) {
  console.log("更改后的数据", Atomics.load(intArrBuffer, 20)); // 返回 99
};
// 这里是 worker 的代码
onmessage = function(e) {
  let arrBuffer = e.data; // 这里就可以获取到
  console.log(Atomics.load(arrBuffer, 20))
  // 我们改一下它
  Atomics.store(arrBuffer, 20, 99); // 返回 99
};

这段代码实际就是在内存中创建了一个 1kb 的内存,然后我将其中的内容循环改成数字后,发送给子进程(还是需要 PostMessage )的,但是内存中的读写速度要比使用 PostMessage 快了很多,感兴趣的老师可以试试

SharedArrayBuffer 是 js 开启多线程的第一步,一提到多线程,我们一定会想到竞争,同样的去修改同一个变量下的同一个元素怎么办?答:多个共享内存的线程能够同时读写同一位置上的数据。原子操作会确保正在读或写的数据的值是符合预期的,即下一个原子操作一定会在上一个原子操作结束后才会开始,其操作过程不会中断。

这个时候就出现了 Atomics, 它对象提供了一组静态方法用来对 SharedArrayBuffer 对象进行原子操作。这些原子操作属于 Atomics 模块。与一般的全局对象不同,Atomics 不是构造函数,因此不能使用 new 操作符调用,也不能将其当作函数直接调用。Atomics 的所有属性和方法都是静态的。

我们来看看它有什么方法:

  • Atomics.add() 将指定位置上的数组元素与给定的值相加,并返回相加前的值
  • Atomics.and() 将指定位置上的数组元素与给定的值相与,返回操作前的值
  • Atomics.load() 返回数组中指定位置的值
  • Atomics.store() 改动其中的某个值,并返回改动后的值
  • Atomics.wait() 如果当前的值等于给定的值,线程会被阻塞等待
  • Atomics.notify() 将当前等待的进程唤醒
    ...

它提供的方法还是很多的,剩下的留给大佬们自己实践一下(测试的时候需要启动服务哈,worke需要)...

你可能感兴趣的:(ES7、ES8 更新点梳理)