第十六节: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. 与空值运算符一起使用
注意:可选链不能用于赋值!!!!!!!
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 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。