Open wuyanqian0503 opened 3 years ago
arr.includes(x)
// 等同于
arr.indexOf(x) >= 0
使用指数运算符**,就像+、-等操作符一样:
console.log(2**10); // 输出1024
async 函数是 Generator 函数的语法糖。使用 关键字 async 来表示,在函数内部使用 await 来表示异步。相较于 Generator,async 函数的改进在于下面四点:
以前,这些符号在字符串文字中被视为行终止符,因此使用它们会导致SyntaxError异常。
如果输入 Unicode 格式但是超出范围的字符,在原先JSON.stringify返回格式错误的Unicode字符串。现在实现了一个改变JSON.stringify的第3阶段提案,因此它为其输出转义序列,使其成为有效Unicode(并以UTF-8表示)
flat()和flatMap()本质上就是是归纳(reduce) 与 合并(concat)的操作。
Array.prototype.flat():
flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
flat()方法最基本的作用就是数组降维
var arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]
var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]
var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]
//使用 Infinity 作为深度,展开任意深度的嵌套数组
arr3.flat(Infinity);
// [1, 2, 3, 4, 5, 6]
其次,还可以利用flat()方法的特性来去除数组的空项
var arr4 = [1, 2, , 4, 5];
arr4.flat();
// [1, 2, 4, 5]
Array.prototype.flatMap()
flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与 map 和 深度值1的 flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些。 这里我们拿map方法与flatMap方法做一个比较。
var arr1 = [1, 2, 3, 4];
arr1.map(x => [x * 2]);
// [[2], [4], [6], [8]]
arr1.flatMap(x => [x * 2]);
// [2, 4, 6, 8]
// 只会将 flatMap 中的函数返回的数组 “压平” 一层
arr1.flatMap(x => [[x * 2]]);
// [[2], [4], [6], [8]]
新增的这两个方法很好理解,分别去除字符串首尾空白字符,这里就不用例子说声明了。
5.Object.fromEntries()
Object.entries()
方法的作用是返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环也枚举原型链中的属性)。
而Object.fromEntries()
则是Object.entries()
的反转。
Object.fromEntries()
函数传入一个键值对的列表,并返回一个带有这些键值对的新对象。这个迭代参数应该是一个能够实现@iterator方法的的对象,返回一个迭代器对象。它生成一个具有两个元素的类似数组的对象,第一个元素是将用作属性键的值,第二个元素是与该属性键关联的值。
通过 Object.fromEntries
, 可以将 Map 转化为 Object:
const map = new Map([ ['foo', 'bar'], ['baz', 42] ]);
const obj = Object.fromEntries(map);
console.log(obj); // { foo: "bar", baz: 42 }
通过 Object.fromEntries, 可以将 Array 转化为 Object:
const arr = [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ];
const obj = Object.fromEntries(arr);
console.log(obj); // { 0: "a", 1: "b", 2: "c" }
通过工厂函数Symbol()创建符号时,您可以选择通过参数提供字符串作为描述:
在 ES10 之前,我们必须通过语法为 catch 子句绑定异常变量,无论是否有必要。很多时候 catch 块是多余的。 ES10 提案使我们能够简单的把变量省略掉。
// 之前是
try {} catch(e) {}
// 现在是
try {} catch {}
javascript 在 Math 上一直很糟糕的原因之一是只能安全的表示-(2^53-1)至 2^53-1 范的值,即Number.MIN_SAFE_INTEGER 至Number.MAX_SAFE_INTEGER,超出这个范围的整数计算或者表示会丢失精度。
var num = Number.MAX_SAFE_INTEGER; // -> 9007199254740991
num = num + 1; // -> 9007199254740992
// 再次加 +1 后无法正常运算
num = num + 1; // -> 9007199254740992
// 两个不同的值,却返回了true
9007199254740992 === 9007199254740993 // -> true
于是 BigInt 应运而生,它是第7个原始类型,可安全地进行大数整型计算。 你可以在BigInt上使用与普通数字相同的运算符,例如 +, -, /, *, %等等。
创建 BigInt 类型的值也非常简单,只需要在数字后面加上 n 即可。例如,123 变为 123n。也可以使用全局方法 BigInt(value) 转化,入参 value 为数字或数字字符串。
const aNumber = 111;
const aBigInt = BigInt(aNumber);
aBigInt === 111n // true
typeof aBigInt === 'bigint' // true
typeof 111 // "number"
typeof 111n // "bigint"
也就是说,只要在数字末尾加上 n,就可以正确计算大数了:
1234567890123456789n * 123n;
// -> 151851850485185185047n
不过有一个问题,在大多数操作中,不能将 BigInt与Number混合使用。比较Number和 BigInt是可以的,但是不能把它们相加。
那么现在的原始数据类型加上BigInt一共有七种,分别是: String、Number、Boolean、Null、Undefined、Symbol、BigInt****
BigInt的支持情况
在查询具有多个层级的对象时、不再需要进行冗余的前置校验.
当引用为null或者undefined的情况下不会引起报错,并且返回值是undefined.
如果表达式在??的左侧运算符求值为 undefined 或 null,就返回其右侧默认值。 排除了 undefined 或 null 以外的如 false、0、空字符串被视为假值造成的繁琐的非空判断。
我们知道 Promise.all 具有并发执行异步任务的能力。但它有一个特点是如果数组中的任何一个promise被reject的话,则整个Promise.all 调用会立即终止,并返回一个reject的新的 Promise 对象。
Promise.allSettled跟Promise.all类似, 其参数接受一个Promise的数组, 返回一个新的Promise, 唯一的不同在于, 它不会进行短路, 也就是说当Promise全部处理完成后,我们可以拿到每个Promise的状态, 而不管是否处理成功。
matchAll()
方法返回一个包含所有匹配正则表达式及分组捕获结果的迭代器。
现在前端打包资源越来越大,前端应用初始化时根本不需要全部加载这些逻辑资源,为了首屏渲染速度更快,很多时候都是动态导入(按需加载)模块,比如懒加载图片等,这样可以帮助您提高应用程序的性能。
其中按需加载这些逻辑资源都一般会在某一个事件回调中去执行:
el.onclick = () => {
import('/modules/my-module.js')
.then(module => {
// Do something with the module.
})
.catch(err => {
// load error;
})
}
import()可以用于script脚本中,import(module) 函数可以在任何地方调用。它返回一个解析为模块对象的 promise。
这种使用方式也支持 await 关键字。
let module = await import('/modules/my-module.js');
通过动态导入代码,您可以减少应用程序加载所需的时间,并尽可能快地将某些内容返回给用户。
globalThis 是一个全新的标准方法用来获取全局 this 。之前开发者会通过如下的一些方法获取:
过去获取全局对象,可通过一个全局函数:
// ES10之前的解决方案
const getGlobal = function(){
if(typeof self !== 'undefined') return self
if(typeof window !== 'undefined') return window
if(typeof global !== 'undefined') return global
throw new Error('unable to locate global object')
}
// ES10内置
globalThis.Array(0,1,2) // [0,1,2]
// 定义一个全局对象v = { value:true } ,ES10用如下方式定义
globalThis.v = { value:true }
globalThis 目的就是提供一种标准化方式访问全局对象
新提案也规定了,Object.prototype 必须在全局对象的原型链中。下面的代码在最新浏览器中已经会返回 true 了:
Object.prototype.isPrototypeOf(globalThis); // true
globalThis的支持情况:
参考:
上沅同学ES6、ES7、ES8、ES9、ES10新特性一览 浪里行舟ES2020新特性
ECMA、ECMAScript与JavaScript的关系
ECMA国际的前身是欧洲计算机制造商协会,是一个信息和电信的标准组织,主要工作是与相关组织合作开发通信技术和消费电子标准。
例如,最开始JavaScript诞生于1994年的网景实验室,1996年,网景将JavaScript提交给ECMA国际进行标准化,ECMA-262标准化的脚本语言在1997年被ECMA组织所采纳,ECMAScript就是这一标准化脚本语言的名称。可以说 JavaScript 是 ECMAScript 的 一个实现和扩展。
ECMA规范最终由TC39敲定。TC39由包括浏览器厂商在内的各方组成,是ECMA的一个委员会组,他们开会推动JavaScript提案沿着一条严格的发展道路前进。 从提案到入选ECMA规范主要有以下几个阶段:
ES6新特性(2015)
ES6的特性比较多,在 ES5 发布近 6 年(2009-11 至 2015-6)之后才将其标准化。两个发布版本之间时间跨度很大,所以ES6中的特性比较多。 在这里列举几个常用的:
1、类
对熟悉Java,object-c,c#等纯面向对象语言的开发者来说,都会对class有一种特殊的情怀。ES6 引入了class(类),让JavaScript的面向对象编程变得更加简单和易于理解。
在ES6以前,继承都是通过一些其他的方式实现的,可以参考 继承的几种方式,其中寄生组合式继承是比较推荐的方式。
注意: 构造函数在类实例化的时候将会被调用,如果不指定,那么会有一个不带参数的默认构造函数 并且子类必须要在constructor中指定super 函数,否则在新建实例的时候会报错. 如果没有置顶consructor,默认带super函数的constructor将会被添加
2、模块化(Module)
ES5不支持原生的模块化,在ES6中模块作为重要的组成部分被添加进来。模块的功能主要由 export 和 import 组成。每一个模块都有自己单独的作用域,模块之间的相互调用关系是通过 export 来规定模块对外暴露的接口,通过import来引用其它模块提供的接口。同时还为模块创造了命名空间,防止函数的命名冲突。
导出(export) ES6允许在一个模块中使用export来导出多个变量或函数。 ES6中一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。
import
ps: NodeJS 从 13.2.0 起开始正式支持 ES Modules 特性,在Node 中使用 ES Modules可以通过在package.json中增加"type": "module"属性来支持。
3.箭头(Arrow)函数
从语法上看,箭头函数是function关键字的简写,但事实上,远不止如此。
详解为什么不能通过new关键字调用
通常JavaScript 函数有两个内部方法:[[Call]] 和 [[Construct]]。
当通过 new 调用函数时,执行 [[Construct]] 方法,创建一个实例对象,然后再执行函数体,将 this 绑定到实例上。 当直接调用的时候,执行 [[Call]] 方法,直接执行函数体。 箭头函数并没有 [[Construct]] 方法,不能被用作构造函数,如果通过 new 的方式调用,会报错。
4、函数参数默认值
支持在定义函数时指定参数的默认值:
5、模板字符串
var name =
Your name is ${first} ${last}.``6、解构赋值
获取数组中的值
获取对象中的值
7、延展操作符/扩展运算符(Spread operator)
延展操作符...
可以在函数调用/数组构造时, 将数组表达式或者string在语法层面展开;还可以在构造对象时, 将对象表达式按key-value的方式展开。延展操作符对对象的支持是在ECMAScript 2018 中提出的新特性。
8、对象属性简写
9、 Promise
Promise 是异步编程的一种解决方案,目的是解决回调地狱的问题,比传统的解决方案callback更加的优雅。它最早由社区提出和实现的,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
Promise 通过then来进行链式调用,解决了回调地狱的问题。
不过即便是可以进行链式调用,在异步操作较多的场景中,还是不太优雅,所以在ECMAScript 2018中,就又提出了 async/await的新特性来解决这一问题。
10、支持let与const
在ES6以前,JS是没有块级作用域的,const与let填补了这方便的空白,const与let都是块级作用域。
使用var定义的变量都会被提升到函数作用域或全局作用域,并且不存在块级作用域,这带来的问题有:
这里我们可以引申到一个常见思考题,就是循环输出的问题,在for循环中调用setTimeout去输出计数:
这个例子就涉及到了块级作用域的作用
const、let 与 var 之间存在的区别有:
不能提升变量和暂时性死区的意义在于: 为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。
const 与 let 的区别
Generator
async await 和 generator