ES6语法总结

57 阅读4分钟

一、let,const命令

1. let命令:

  • 块级作用域,存在暂存死区,不允许重复声明,不存在变量提升;

2. cosnt命令:

  • 声明只读常量,值不能改变;(本质上是变量指向的那个内存地址保存的数据不能变动,因此对于简单的数据类型,值就保存在变量存在的地址;对于复合类型,const只能保证这个指针是固定的,无法控制他的数据结构是否可变)
const foo = {}
// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123
// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only
const a = [];
a.push('Hello'); // 可执行
a.length = 0;    // 可执行
a = ['Dave'];    // 报错
上面代码中,常量`a`是一个数组,这个数组本身是可写的,但是如果将另一个数组赋值给`a`,就会报错。

如果真的想将对象冻结,应该使用Object.freeze方法。

const foo = Object.freeze({});
// 常规模式时,下面一行不起作用;
// 严格模式时,该行会报错
foo.prop = 123;

二、解构赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构、

注意:

1、被解构数据不能为undefined,null,NaN等

2、已申明变量解构赋值,需注意js引擎将{}识别为代码块;如:

// 错误的写法
let x;
{x} = {x: 1};
// SyntaxError: syntax error
//JavaScript 引擎会将`{x}`理解成一个代码块,从而发生语法错误
//正确写法
({x} = {x: 1});

3、数组本质是特殊的对象,因此可以对数组进行对象属性的解构

let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3

4、字符串解构赋值。

这是因为此时,字符串被转换成了一个类似数组的对象。( 数值和布尔值同理)

const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"

let {length : len} = 'hello';
len // 5

5、提高代码优雅性的解构赋值

我们在对接中经常会出现前后端字段不一致的情况,在赋值的时候会出现很多重复代码看着会很难受,,如:

//初始化表单  这样看着就很难受
 const setData = (row: any) => {
      form.a = row.aa;
      form.b = row.bb;
      form.c = row.cc;
    };

//使用解构赋值优化后  一行代码就可以解决
 const setData = (row: any) => {
     const { aa : form.a, bb : form.b, cc : form.c } = row;
    };


三、运算符扩展

1、指数运算符(**

2 ** 2 // 4
2 ** 3 // 8
//还可以和 = 结合使用
let a = 1;
a **= 2;
//等同于 a = a * a

2、链判断运算符(?.

三种用法:

  • obj?.prop // 对象属性是否存在
  • obj?.[expr] // 同上
  • func?.(...args) // 函数或对象方法是否存在
const firstName = message?.body?.user?.firstName || 'default';

let hex = "#C0FFEE".match(/#([A-Z]+)/i)?.[1];

iterator.return?.()

3、Null 判断运算符(??

读取对象属性的时候,如果某个属性的值是nullundefined,有时候需要为它们指定默认值。常见做法是通过||运算符指定默认值。

但是通过 || 来判断是有错误的,当他的属性值为空字符串、false0时默认值也会生效。这样就与我们的实际要求不符合。

为了避免这种情况引入了??(null判断运算符)

//这个运算符很适合判断函数参数是否赋值。
function Component(props) {
  const enable = props.enabled ?? true;
  // …
}

4、逻辑赋值运算符

// 或赋值运算符
x ||= y
// 等同于
x || (x = y)

// 与赋值运算符
x &&= y
// 等同于
x && (x = y)

// Null 赋值运算符
x ??= y
// 等同于
x ?? (x = y)

这三个运算符||=&&=??=相当于先进行逻辑运算,然后根据运算结果,再视情况进行赋值运算。

它们的一个用途是,为变量或属性设置默认值。

四、Proxy

1、概述

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写;

var obj = new Proxy({}, {
  get: function (target, propKey, receiver) {
    console.log(`getting ${propKey}!`);
    return Reflect.get(target, propKey, receiver);
  },
  set: function (target, propKey, value, receiver) {
    console.log(`setting ${propKey}!`);
    return Reflect.set(target, propKey, value, receiver);
  }
});

var proxy = new Proxy(target, handler);

Proxy 对象的所有用法,都是上面这种形式,不同的只是handler参数的写法。其中,new Proxy()表示生成一个Proxy实例,target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为。

浏览器录像功能:


const body = document.body;
body.addEventListener('click', async function () {
  const stream = await navigator.mediaDevices.getDisplayMedia({ video: true });
  const mime = MediaRecorder.isTypeSupported('video/webm; codecs=vp9') ? 'video/webm; codecs=vp9' : 'video/webm';
  const mediaRecorder = new MediaRecorder(stream, { mimeType: mime }); // 录制
  const chunks = [];
  mediaRecorder.addEventListener('dataavailable', function (e) {
    chunks.push(e.data);
  }); 
  mediaRecorder.addEventListener('stop', function () {
    const blob = new Blob(chunks, { type: chunks[0].type });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'video.webm';
    a.click();
  });
  mediaRecorder.start();
});