第十六节:ES7--ES12基础知识详解

一. ES7 (ES2016)

1. includes方法

(1). 作用:用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false

(2). 用法:

      A. 一个参数的时候:直接从数组中查找,有则true,反之false

      B. 两个参数的时候:第二个参数代表从索引位置开始

注:和indexof的区别:

    两者都是采用===的操作符来作比较的,不同之处在于:对于NaN的处理结果不同。我们知道js中 NaN === NaN 的结果是false, indexOf()也是这样处理的,但是includes()不是这样的。  

{
    const names = ["abc", "cba", "nba", "mba", NaN];
    console.log(names.includes("cba")); //true
    // 从索引为1的位置开始查找
    console.log(names.includes("cba", 1)); //true
    // 从索引为2的位置开始查找
    console.log(names.includes("cba", 2)); //false
    console.log(names.includes(NaN)); //true

    // 在这之前通常是通过indexof来判断
    console.log(names.indexOf("cba") != -1); //true
    // 在处理NaN上,和includes不同
    console.log(names.indexOf("NaN") != -1); //false
}

 

2. 幂运算符**

    实现一个数的求幂运算

    比如:2的10次方,之前的写法:Math.pow(2, 10)   现在的写法:2 ** 10

{
    // 求2的10次方

    // 之前的写法
    console.log(Math.pow(2, 10)); //1024

    // ES7的写法
    console.log(2 ** 10); //1024
}

 

二. ES8 (ES2017)

1. Object新增方法

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

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

    (3).Object.getOwnPropertyDescriptors(): 方法用来获取一个对象的所有自身属性的描述符。

{
    const obj = {
        name: "ypf",
        age: 18,
        height: 188,
    };
    //Object.values()
    console.log(Object.values(obj)); // [ 'ypf', 18, 188 ]
    // Object.entries()
    console.log(Object.entries(obj)); //[ [ 'name', 'ypf' ], [ 'age', 18 ], [ 'height', 188 ] ]
    for (const [key, value] of Object.entries(obj)) {
        console.log(key, value);
    }
    //getOwnPropertyDescriptors
    console.log(Object.getOwnPropertyDescriptors(obj));
    // 下面是输出结果
    // {
    //     name: {
    //       value: 'ypf',
    //       writable: true,
    //       enumerable: true,
    //       configurable: true
    //     },
    //     age: { value: 18, writable: true, enumerable: true, configurable: true },
    //     height: { value: 188, writable: true, enumerable: true, configurable: true }
    //   }
}

 

2. String新增方法

    (1). padStart():把指定字符串填充到字符串头部,符合指定的长度,返回新字符串,如果不指定填充字符串,则用空格填充.

    (2). padEnd():把指定字符串填充到字符串尾部,符合指定的长度,返回新字符串,如果不指定填充字符串,则用空格填充.

{
    const str = "lmr";
    // 用x从开头位置进行填充,使其长度达到8
    console.log(str.padStart(8, "x")); // xxxxxlmr
    // 用y从结尾位置进行填充,使其长度达到8
    console.log(str.padEnd(8, "y")); //lmryyyyy
    console.log(str.padStart(8)); //     lmr

    // 案例1--日期格式化
    {
        const now = new Date();
        const year = now.getFullYear();
        const month = (now.getMonth() + 1).toString().padStart(2, "0");
        const day = now.getDate().toString().padStart(2, "0");
        console.log(year, month, day);
        console.log(`${year}-${month}-${day}`); //2022-03-21
    }
    // 案例2-数字替换
    {
        // 数字替换,比如手机号,身份证号
        const tel = "13012345678";
        // 截取后四位,然后从开头用*填充
        const newTel = tel.slice(-4).padStart(tel.length, "*");
        console.log(newTel); // *******5678
    }
}

 

3. 尾逗号 Trailing commas

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

function foo(m, n,) {}
foo(20, 30,);

 

4. async/await

      后面具体单独介绍

 

三. ES9 (ES2018)

    1. for await of: 后面详解

    2. RegExp Updates:实际用处不大

    3. Object Rest & Spread:剩余参数和展开运算符,前面已经讲过了【这里是针对对象来使用】  详见:https://www.cnblogs.com/yaopengfei/p/16027402.html

    4. Promise.prototype.finally():后面详解

    5. 字符串扩展:ES9开始,模板字符串允许嵌套支持常见转义序列,移除对ECMAScript在带标签的模版字符串中转义序列的语法限制。

{
    function tag(strs) {
        console.log(strs);
        // strs[0] === undefined
        // strs.raw[0] === "\\unicode and \\u{55}"
    }

    // 在标签函数中使用
    tag`\u{61} and \u{62}`; //
    tag`\u{61} and \unicode`; // 结果是 undefined

    // 之前的版本会报错:Invalid Unicode escape sequence
    // 无效的Unicode转义序列

    // 报错:
    let bad = `bad escape sequence: \unicode`;
}

 

四. ES10 (ES2019)

1. Object扩展

(1) Object.fromEntries(): 把键值对列表转换为一个对象,这个方法是和 Object.entries() 相对的

(2). 案例:

      A. 将Map类型的数据转为Object

      B. 过滤

      C. url的Search参数转换

{
    let myObj = {
        name: "ypf",
        age: 18,
        height: 1.82,
    };
    // 先利用entries将对象转换成键值对数组
    let myArray1 = Object.entries(myObj);
    console.log(myArray1); //[ [ 'name', 'ypf' ], [ 'age', 18 ], [ 'height', 1.82 ] ]
    // 利用fromEntries把键值对数组转换成对象
    console.log(Object.fromEntries(myArray1)); //{ name: 'ypf', age: 18, height: 1.82 }
}
// 案例
{
    // 1. 将Map类型的数据转为Object
    const map1 = new Map();
    map1.set("name", "ypf");
    map1.set("age", 18);
    map1.set("height", 1.82);
    console.log(map1); //Map(3) { 'name' => 'ypf', 'age' => 18, 'height' => 1.82 }
    // 转换成对象
    console.log(Object.fromEntries(map1)); //{ name: 'ypf', age: 18, height: 1.82 }

    //2. 过滤-请课程分数大于90的课程组成的对象
    let course = {
        math: 91,
        english: 85,
        chinese: 95,
    };
    let temp = Object.entries(course).filter(([key, value]) => value > 90);
    console.log(temp); //[ [ 'math', 91 ], [ 'chinese', 95 ] ]
    // 转换为对象
    console.log(Object.fromEntries(temp)); //{ math: 91, chinese: 95 }

    // 3. url的Search参数转换
    // let url = "https://www.baidu.com?name=ypf&age=18&height=1.88"
    // queryString 为 window.location.search
    const queryString = "?name=ypf&age=18&height=1.88";
    const queryParams = new URLSearchParams(queryString);
    const paramObj = Object.fromEntries(queryParams);
    console.log(paramObj); // { name: 'ypf', age: '18', height: '1.88' }
}

 

2. Array扩展

(1).flat()方法: 会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。不传递参数按照1来计算。

(2).flatMap()方法: 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。

        注意一:flatMap是先进行map操作,再做flat的操作;

        注意二:flatMap中的flat相当于深度为1;

{
    // flat
    const nums = [
        10,
        20,
        [2, 9],
        [
            [30, 40],
            [10, 45],
        ],
        78,
        [55, 88],
    ];
    // 默认按照1来计算
    console.log(nums.flat()); //[ 10, 20, 2, 9, [ 30, 40 ], [ 10, 45 ], 78, 55, 88 ]
    // 指定深度为2
    console.log(nums.flat(2)); //[ 10, 20, 2, 9, [ 30, 40 ], [ 10, 45 ], 78, 55, 88 ]
    // flatMap
    const nums2 = [10, 20, 30];
    const newNums3 = nums2.flatMap(item => {
        return item * 2;
    });
    const newNums4 = nums2.map(item => {
        return item * 2;
    });
    console.log(newNums3); //[ 20, 40, 60 ]
    console.log(newNums4); //[ 20, 40, 60 ]
    // 3.flatMap的应用场景
    const messages = ["Hello World", "hello lyh", "my name is coderwhy"];
    const words = messages.flatMap(item => {
        return item.split(" ");
    });
    console.log(words); //["Hello", "World", "hello", "lyh", "my", "name", "is", "coderwhy"];
}

 

3. String扩展

(1).trimStart()方法:左边去空格

(2).trimEnd()方法:右边去空格

{
    let msg1 = "    ypf";
    let msg2 = "ypf    ";
    let msg3 = "    ypf   ";
    console.log(msg1.trimStart()); //ypf
    console.log(msg2.trimEnd()); //ypf
    console.log(msg3.trim()); //ypf
}

 

4. try-catch

  可以省略catch中的error参数

{
    try {
        console.log("Foobar");
    } catch {
        console.error("Bar");
    }
}

 

5. Symbol扩展

     可以通过 description 方法获取 Symbol 的描述:

{
    const name = Symbol("es");
    console.log(name.description); // es
    name.description = "es2"; // 只读属性 并不能修改描述符
    console.log(name.description === "es"); // true
    // 如果没有描述符 输入undefined
    const s2 = Symbol();
    console.log(s2.description); // undefined
}

 

 

五. ES11(ES2020)

1. BigInt类型

 在 ES10 增加了新的原始数据类型:BigInt,表示一个任意精度的整数,可以表示超长数据,可以超出2的53次方。  Js 中 Number类型只能安全的表示-(2^53-1)至 2^53-1 范的值

 使用 BigInt 有两种方式:

    (1). 数字后面增加n  

    (2).使用 BigInt 函数

{
    // 方式1
    const bigInt = 9007199254740993n;
    console.log(bigInt);
    console.log(typeof bigInt); // bigint
    console.log(1n == 1); // true
    console.log(1n === 1); // false
    // 方式2
    const bigIntNum = BigInt(9007199254740993n);
    console.log(bigIntNum);
}

 

2. globalThis

 我们以往获取全局对象的方式如下:所以我们通常需要封装个方法

     (1). node 中通过 global

     (2). web 中通过 window, self 等.  

  ES11中无论node 或 web下,统一通过globalThis来获取

{
    // ES11之前获取全局对象的方式
    const getGlobal = () => {
        if (typeof self !== "undefined") {
            return self;
        }
        if (typeof window !== "undefined") {
            return window;
        }
        if (typeof global !== "undefined") {
            return global;
        }
        throw new Error("无法找到全局对象");
    };
    const globals = getGlobal();
    // console.log(globals);

    // ES11通过globalThis
    console.log(globalThis);
}

 

3. 可选链 Optional chaining ?  【重点】

(1). 背景:

        多层级的对象时,调用内层的属性或方法,需要加前置校验,判断是否存在,否则会导致程序报错,中断,无法执行下面的业务。

(2). 可选链的符号:?

(3). 可选链的用法:可选链中的 ? 表示【如果问号左边表达式有值, 就会继续查询问号后面的字段】

      A. 对象中使用:调用属性和方法

      PS:对于方法而言,注意一下下面的两种写法的含义的区别

       console.log(userInfo?.myChild2?.getMsg()); //undefined  (表示当userInfo存在且myChild2存在的时候调用getMsg())

       console.log(userInfo?.myChild2?.getMsg?.()); //undefined (和上边有区别,这里表示当userInfo存在且myChild2存在且getMsg存在的时候才调用)

      B. 数组中使用

      C. 与空值运算符一起使用

 注意:可选链不能用于赋值!!!!!!!

详见:https://www.cnblogs.com/yaopengfei/p/16049076.html

4. 空值合并运算符(Nullish coalescing Operator) ??  【重点】

(1) 背景:

        解决了之前逻辑或操作符(||)的几个弊端:

        ||的含义:左侧操作数为假值时返回右侧操作数。也就是说,如果使用 || 来为某些变量设置默认值,可能会遇到意料之外的行为。

        比如为假值(例如'',0,NaN,false)时

(2). 符号: ??

(3). 用法:当左侧的操作数为 null或者undefined时,返回其右侧操作数,否则返回左侧操作数。

详见:https://www.cnblogs.com/yaopengfei/p/16049076.html


5. Dynamic Import

     使用的时候按需导入


6. Promise.allSettled()

     在promise章节单独介绍

 

六. ES12 (ES2021)

1. 各种运算符

(1). ||=  逻辑或赋值运算

       含义: 形如 x ||= y 运算仅在 x 为false时,返回右侧的值y,否则仍然返回值x, 实际上可以认为它是 x||(x=y) 的缩写,所以 ||= 也存在一下意外的bug,比如:0、“”、NaN、false,都认为是false,都会

               执行 ||= 右侧的代码

        PS:针对null 和 undefined,执行右侧代码这是我们所需要的,是正确的。

(2). &&=  逻辑与赋值运算

       含义:形如 x &&= y 运算仅在 x 为ture时,返回右侧的值y,否则仍然返回值x, 实际上可以认为它是 x && (x=y) 的缩写

       PS:除了 0、“”、NaN、false、null、undefined以外,都为ture

(3). ??=  逻辑空赋值运算符

      含义:形如 x ??= y 运算仅在 x 为null或undefined时,返回右侧的值y,否则仍然返回值x, 实际上可以认为它是 x ?? (x=y) 的缩写

详见:https://www.cnblogs.com/yaopengfei/p/16049076.html


2. FinalizationRegistry(了解)

   该对象可以让你在对象被垃圾回收时请求一个回调。

(1).FinalizationRegistry 提供了这样的一种方法:当一个在注册表中注册的对象被回收时,请求在某个时间点上调用一个清理回调。(清理回调有时被称为 finalizer );

(2).你可以通过调用register方法,注册任何你想要清理回调的对象,传入该对象和所含的值;

{
    const finalRegistry = new FinalizationRegistry(value => {
        console.log("注册在finalRegistry的对象, 某一个被销毁", value);
    });

    let obj = { name: "why" };
    let info = { age: 18 };

    finalRegistry.register(obj, "obj");
    finalRegistry.register(info, "value");

    obj = null;
    info = null;
}

 

3. WeakRefs(了解)

   如果我们默认将一个对象赋值给另外一个引用,那么这个引用是一个强引用:

   如果我们希望是一个弱引用的话,可以使用WeakRef;

{
    // ES12: WeakRef类
    // WeakRef.prototype.deref:
    // > 如果原对象没有销毁, 那么可以获取到原对象
    // > 如果原对象已经销毁, 那么获取到的是undefined
    const finalRegistry = new FinalizationRegistry(value => {
        console.log("注册在finalRegistry的对象, 某一个被销毁", value);
    });

    let obj = { name: "why" };
    let info = new WeakRef(obj);

    finalRegistry.register(obj, "obj");

    obj = null;

    setTimeout(() => {
        console.log(info.deref()?.name);
        console.log(info.deref() && info.deref().name);
    }, 10000);
}

 

4. String.prototype.replaceAll()

    replaceAll()  方法返回一个新字符串,新字符串中所有满足 pattern 的部分都会被replacement 替换。

    pattern可以是一个字符串或一个RegExp,replacement可以是一个字符串或一个在每次匹配被调用的函数。原始字符串保持不变。

注意:使用正则表达式搜索值时,它必须是全局的。

{
    console.log("aabbcc".replaceAll("b", ".")); // 'aa..cc'

    // 报错:TypeError: replaceAll must be called with a global RegExp
    // console.log("aabbcc".replaceAll(/b/, "."));

    console.log("aabbcc".replaceAll(/b/g, ".")); //aa..cc
}

 

 

 

 

 

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 

 

posted @ 2022-03-29 09:31  Yaopengfei  阅读(478)  评论(1编辑  收藏  举报