ES6新特性,ES6详解
文章目录
- ES6新特性,ES6详解
- 1:前言
- 2:let与const
- 3:Promise 异步操作
- 4:Class 类
- 5:箭头函数
- 6:函数默认值
- 7:模版字符串
- 8:解构赋值
- 9:展开语法
- 10:对象属性缩写
- 11:模块化
- 12:includes
- 13:指数运算符
- 14:async/await
- 15:Object对象遍历
- 16:Object.getOwnPropertyDescriptors()
- 17:padStart()/padEnd()
- 18:ShareArrayBuffer
- 19:Atomics
- 20:尾后逗号
- 21:for await 异步迭代
- 22:关于《带标签的模板字符串》非法转义序列的修订
- 23:正则拓展
- 24:JSON.stringify 增强编码问题(转义字符串)
- 25:flat
- 25:flatMap
- 26:trimStart/trimEnd 去除空格
- 27:Object.fromEntries()
- 28:Symbol.prototype.description
1:前言
该 ES6
内容包含了 ES7
、ES8
、ES9
、ES10
、ES11
的特性。我们通常会使用 ES6
来统一概括这些新特性。
2:let与const
2.1:let、const
- 块级作用域
{
let a = 888;
}
/**
* Uncaught ReferenceError: a is not defined
*/
console.log(a);
- 不会变量提升
/**
* Uncaught ReferenceError: a is not defined
*/
console.log(a);
{
let a = 888;
}
- 同一作用域不可以重复声明
{
let a = 888;
/**
* Uncaught SyntaxError: Identifier 'a' has already been declared
*/
let a = 666;
}
2.2:let与const的不同
大部分特性相同,不同点:
const 设置的变量不可以再修改(对象类型除外)。
const a = 888;
/**
* Uncaught TypeError: Assignment to constant variable.
*/
a = 999;
const a = {};
/**
* 成功
*/
a.name = 'anny';
3:Promise 异步操作
3.1:Promise
状态:
- 待定(pending):初始状态。
- 已完成(fulfilled):操作成功完成。
- 已拒绝(rejected):操作失败。
3.2:Promise
实例方法:
- then():完成
new Promise((resolve,reject)=>{
resolve(888)
})
.then(res=>{
console.log(res)
})
- catch():失败
new Promise((resolve,reject)=>{
reject(888)
})
.catch(err=>{
console.log(err)
})
- finally():无论成功/失败都执行
let num = 100;
new Promise((resolve,reject)=>{
if(num==100){
resolve(888)
}else{
reject(999)
}
})
.then(res=>{
console.log(res)
})
.catch(err=>{
console.log(err)
})
.finally(info=>{
console.log('finally!')
})
3.3:Promise
链式调用:
new Promise((resolve,reject)=>{
resolve()
})
.then(res=>{
console.log(888)
})
.then(res=>{
console.log(999)
})
.then(res=>{
console.log(666)
})
3.4:Promise
同步执行异步函数:
实现同步执行异步函数,只需要在每个回调中返回一个 Promise
对象即可。
function asyncMeth_one(){
return new Promise(resolve=>{
setTimeout(() => {
console.log('run 800!');
resolve()
}, 800);
})
}
function asyncMeth_two(){
return new Promise(resolve=>{
setTimeout(() => {
console.log('run 500!')
resolve()
}, 500);
})
}
new Promise((resolve,reject)=>{
resolve()
})
.then(res=>{
return asyncMeth_one();
})
.then(res=>{
return asyncMeth_two();
})
4:Class 类
4.1:constructor 构造器
当使用 new
关键词调用 类
时,会自动调用 constructor
。
class People{
constructor(){
console.log('被 new 了');
}
}
new People();
4.2:super
当继承时,如果子类使用了 constructor
构造器,则必须使用 super
关键词。
class Earth {
constructor(name){
this.name = name;
}
}
class People extends Earth{
constructor(){
super('anny');
console.log(this.name);
}
}
new People();
5:箭头函数
5.1:没有自己的 this
箭头函数的 this
指向作用域链的上一层。
function test(){
this.name = 'anny';
let arrow = ()=>{
console.log(this.name);
}
arrow();
}
test();
5.2:不可以使用 new
命令
因为箭头函数没有自己的 this
,所以不可以用做 构造函数
。
5.3:没有 arguments
对象
5.4:不能用做 Generator
函数
6:函数默认值
函数参数可以设置默认值:
function test(a,b=100){
return a+b;
}
console.log(test(80));
注意:函数默认值不会更改函数 arguments
的值。
7:模版字符串
通常,我们需要非常复杂的连接字符串。
function test(){
let name = 'anny';
let age = 22;
return "My name is " + name + "; age is "+ age;
}
console.log(test());
但是我们可以通过使用模板字符串来大大简化这一点。
function test(){
let name = 'anny';
let age = 22;
return `My name is ${name}; age is ${age}`;
}
console.log(test());
8:解构赋值
8.1:解构对象
let obj = {
name:'anny',
age:22
}
let {age} = obj;
console.log(age);
8.1.1 设置别名:
let obj = {
name:'anny',
age:22
}
let {age:Myage} = obj;
console.log(Myage);
8.1.2 动态名称:
let key = 'age';
let obj = {
name:'anny',
age:22
}
let {[key]:Myage} = obj;
console.log(Myage);
8.2:解构对象使用/例子
我们这里拿 console
为例:
let {log} = console;
log(888);
8.3:解构数组赋值
let [a] = [1,2,3,4,5,6];
console.log(a);
8.3.1:解构数组指定位置
只使用部分位置下标值,可以使用 逗号
分割。
let [,,,a] = [1,2,3,4,5,6];
console.log(a);
这里输出 4
。
8.4:解构数组
let a = [1,2,3,4,5,6];
console.log(...a);
9:展开语法
9.1:函数传值
function test(a, b, c) {
console.log(`a:${a},b:${b},c:${c}.`)
}
let arr = [1,2,3];
test(...arr); //a:1,b:2,c:3.
9.2:函数接收值
function test(...a) {
console.log(a)
}
let arr = [1, 2, 3];
test(...arr); //[1,2,3]
9.3:连接多个数组
let arr1 = [4, 5, 6];
let arr2 = [1, 2, 3, ...arr1];
console.log(arr2); //[1,2,3,4,5,6]
10:对象属性缩写
对象属性名
和 变量/函数
名称相同时就可以进行缩写。
比如:
let age = 20;
let obj = {
age: age
}
/**
* 缩写
*/
let obj1 = {
age
}
let obj = {
speak: function speak() {
console.log('speak')
}
}
/**
* 缩写
*/
let obj1 = {
speak() {
console.log('speak')
}
}
11:模块化
注意:script
标签使用模块化需要设置 type="module"
属性。另外,本地运行,会有跨域提醒。需要搭建一个服务器解决。
11.1:import 引入
11.1.1:解构取值
import {name} from './test.js'
11.1.2:设置别名
import {name as names} from './test.js'
11.1.3:赋值对象
import * as names from './test.js'
console.log(names.name)
11.2:export 导出
11.2.1:export
export const name = 'anny';
export const age = 22;
11.2.2:export default
export default {
name:'anny',
age:20
}
11.2.3:export 和 export default 的区别
- import引入大部分相同,export default支持单独使用一个变量引入:
import name from './test.js'
- export 支持多次导出,而 export default 只可导出一次:
12:includes
includes用于判断数组中是否包含指定的值。
返回值:true/false
let arr = [1,2,3];
console.log(arr.includes(2))
可以指定查找 起始位置
。
let arr = [1,2,3];
console.log(arr.includes(2,1))
13:指数运算符
console.log(2**3) //8
等同于:2*2*2
14:async/await
用于同步执行异步函数:
14.1:误区——使用就会同步执行异步代码
async function test() {
await setTimeout(() => {
console.log(8888)
}, 2000);
console.log(999)
}
test(); //999 8888
其实 await
渴望接收一个 Promise
期约:
function asyncMeth(){
return new Promise(resolve=>{
setTimeout(()=>{
console.log(8888)
resolve();
},1000)
})
}
async function test() {
await asyncMeth();
console.log(999)
}
test(); // 8888 999
14.2:一旦使用了 await ,await 之后的代码(包括同步)都会异步执行
async function test() {
await console.log(888);
console.log(999)
}
test();
console.log(666)
输出:888 666 999
15:Object对象遍历
15.1:Object.values()
返回一个包含对象所有 属性值
的数组。
和 for in
的区别,for in
会遍历原型链。
let obj = {
name:'anny',
age:20
}
console.log(Object.values(obj));
输出:['anny', 20]
15.2:Object.keys()
返回一个包含对象所有 属性名
的数组。
let obj = {
name:'anny',
age:20
}
console.log(Object.keys(obj));
输出:['name', 'age']
15.3:Object.entries()
返回一个包含对象自身可枚举属性的键值对数组。
let obj = {
name:'anny',
age:20
}
console.log(Object.entries(obj));
输出:[['name', 'anny'] , ['age', 20]]
16:Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptors() 方法用来获取一个对象的所有自身属性的描述符
。
对象属性描述符:
- configurable:属性
描述符
是否可以被改变/删除(默认false) - enumerable:是否可以被枚举(默认false)
- value:属性对应的值(默认undefined)
- writable:属性值
value
是否可以被改变(默认false)
17:padStart()/padEnd()
padStart()/padEnd()
都属于填充字符串,只是填充开始位置不同。
17.1:padStart()
let str = '7878'
console.log(str.padStart(10,"*"))
输出:******7878
17.1:padEnd()
let str = '7878'
console.log(str.padEnd(10,"*"))
输出:7878******
18:ShareArrayBuffer
JavaScript 是单线程的,如果要使用多线程,可以使用 Workers
对象:
主线程用于与用户交互,Worker
线程用于承担计算任务
var myWorker = new Worker('test.js');
SharedArrayBuffer
的大部分作用是创建一块公共内存,供 主线程
和 Workers
线程共同读写。
19:Atomics
Atomics
作用是提供一组静态方法对 SharedArrayBuffer
和 ArrayBuffer
对象进行原子操作。
什么是原子操作?
原子操作:多个共享内存的线程能够同时读写同一位置上的数据。原子操作会确保正在读或写的数据的值是符合预期的,即下一个原子操作一定会在上一个原子操作结束后才会开始,其操作过程不会中断。
20:尾后逗号
let arr = [
1,
2,
3
]
如果想要在数组中再添加一条数据(第 5
行),需要先在第 4
行添加一个 逗号
,然后再添加数据。但在 版本比较
中会提醒第 4
行发生了改变。
为了方便 比较(diff)
,提案了 尾后逗号
。
它看起来就像这样:
let arr = [
1,
2,
3,
]
21:for await 异步迭代
for await 可异步迭代 实现异步迭代器协议的对象
。
function * asyncMeth(){
yield import('./test.js')
yield import('./test3.js')
}
for await (let aa of asyncMeth()) {
console.log(aa);
}
22:关于《带标签的模板字符串》非法转义序列的修订
22.1:什么是带标签的模板字符串
function test(msg) {
console.log(msg)
}
test`this is anny`
22.2:带标签的模版字面量及转义序列
- Unicode 字符以"\u"开头,例如\u00A9
- Unicode 码位用"\u{}"表示,例如\u{2F804}
- 十六进制以"\x"开头,例如\xA9
- 八进制以""和数字开头,例如\251
22.3:为什么修订非法转义序列
就像看到的关于22.2:《带标签的模版字面量及转义序列》
,解析器转义都是根据那些规则去查找有效的转义序列。
但提议者认为带标签的模版字符串应该 允许嵌套支持常见转义序列
的语言。
如:
function test(msg) {
console.log(msg)
}
test`\unicode`
如果根据 22.2:《带标签的模版字面量及转义序列》
规则,该功能不能运行。
总的概括来说,就是允许更广泛的自定义写法,可以使用 undefined
代替解析不了的值,使用 raw
返回原始传入的字符串,而不是无法运行的 报错
。
23:正则拓展
这里只列出了一部分,更多详情请到搜索引擎查询。
23.1:具名组匹配
首先看一下 组匹配
:
let rep= /(\w{5})-(\w{8})/;
console.log(rep.exec("China-ShanDong"))
输出:
0: "China-ShanDong"
1: "China"
2: "ShanDong"
groups: undefined
index: 0
input: "China-ShanDong"
length: 3
加个名称构成 具名组匹配
(名称尽量使用英文,这里仅便于观察):
let rep= /(?<国家>\w{5})-(?<城市>\w{8})/;
console.log(rep.exec("China-ShanDong"))
输出:
0: "China-ShanDong"
1: "China"
2: "ShanDong"
groups:{
国家: "China"
城市: "ShanDong"
}
index: 0
input: "China-ShanDong"
length: 3
23.2:引入
可以使用 \k<组名>$
的写法引用某个 具名组匹配
。
let rep= /(?<名字>\w{4})-\k<名字>$/;
console.log(rep.test("anny-anny")) // true
console.log(rep.test("anny-anny1")) // false
24:JSON.stringify 增强编码问题(转义字符串)
对于 无法编码
的字符串,返回 转义字符串
。
简单来说就是遇到无法编码的字符串时,直接返回你传入的原始字符串(之前是报错)。
25:flat
按照指定的深度递归数组,将所有元素和遍历到的子数组数据合并为一个新数组返回。
let arr = [1,2,3,[4,5,6]]
console.log(arr.flat(1))
输出:[1, 2, 3, 4, 5, 6]
let arr = [1,2,3,[[4,5,6]]]
console.log(arr.flat(1))
输出:[1, 2, 3, [4, 5, 6]]
25:flatMap
flatMap
使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与 flat(1)
返回的值几乎相同。
let arr = [1,2,3,[4,5,6]]
console.log(arr.flatMap(e=>e))
输出:[1, 2, 3, 4, 5, 6]
26:trimStart/trimEnd 去除空格
顾名思义,一个是删除开始位置的空格,另一个是删除末尾位置的空格。
let str =` 123 `;
console.log(str.trimStart())
console.log(str.trimEnd())
27:Object.fromEntries()
Object.fromEntries()
作用是把键值对列表转换为一个对象。
如:
let arr = [
['name','anny'],
['age',20]
]
console.log(Object.fromEntries(arr));
输出:
{
age: 20
name: "anny"
}
28:Symbol.prototype.description
Symbol.prototype.description
:返回 Symbol
对象的可选描述的字符串。
与 Symbol.prototype.toString()
的区别:
let a = Symbol('hello')
console.log(a.toString())
console.log(a.description);
a.toString()
输出:Symbol(hello)
a.description
输出:hello