ES6-ES11新特性速查手册

ES6-ES11

es6新特性:let、const、解构赋值、模板字符串、对象简化写法(kv一致省略v)、箭头函数、函数参数默认值、rest 参数,扩展运算符、Symbol 类型、迭代器、生成器、Promise、Set、Class 类、模块化、super

1、let

let:在全局或者块中都只能独立声明一次,作用域是块级,有暂时性死区(也就是不会变量提升)/*不会影响作用域链*/
如果通过 var 遍历循环绑定的点击事件会导致变量覆盖,所以批量声明点击事件的时候用 let 作为循环体的循环变量

2、const

const:只能声明一次且有初始值,不能被修改值,如引用类型(数组、对象)的话在不修改内存地址执行的情况下可以修改值(不整个修改的前提可以通过索引或者属性名修改)   一般全大写命名,用来声明数组和对象比较稳妥,防止误操作

3、解构赋值

如果解构对象中方法要将this指向指回原对象,xxx.call( obj ),否则this会被变为window对象,const适用于声明数组、对象,防止误操作,大写声明
// 连续解构赋值 + 重命名,下面两条语句等价,前者中不能单独访问 k(连续解构) 以及 v(重命名) 这两个变量,访问了会报错
const {k:{v:keyWord}} = this	--->	const {v:keyWord} = this.k

4、模板字符串

1.6、模板字符串( 模板字面量+字符串插值
基本定义: ` ${ 变量 } `	 // 可随意换行以及拼接串

5、对象简化写法

k、v一致省略 v 的操作是 es6 的语法,对象中省略 v 会通过作用域链在外部查找对应的变量

6、箭头函数

this 没有自己的 this 指向:1、this是静态的,始终指向声明时所在作用域下的this(箭头函数指向的定义时,外层第一个普通函数的this);2、不能作为构造函数实例化对象;3、不能使用 arguments 变量;4、this指向是不可被修改的(call、apply、bind)并且是没有原型的prototype(输出undefined);5、一形参时可以省略括号;6、当代码体只有一条语句时可以省略 括号 和 return
/* this 指向很关键,箭头函数的 this 是指向声明时所在作用域下的 this,和作用域牵扯
   		箭头函数适用于与 this 无关的回调,如定时器,数组的方法回调
         箭头函数不适用于与 this 有关的回到,如事件绑定时的回调,对象的方法(不适用不代表不能用) */
window.name = 'sgg'
const school = {
    name: 'ggs',
    getName2: () => {
        console.log(this.name)		// 该this就会被指向window,因为声明在全局作用域中
    }
}
school.getName2()

7、函数参数默认值

// 默认值:函数的默认值一般都是靠后赋值(潜规则),否则实参传入可能导致参数值错乱,可搭配解构赋值适用
function fn(a, b, c = 10) {					function fn({a, b, c = 10}) {
    console.log(a, b, c);						console.log(a, b, c);
}										  }
fn(1, 5)								   fn({a:1,b:2})

8、rest 参数

实则就是扩展运算符在函数形参中的使用
// 必须放在最后接收,否则报错,接收整合成一个数组,可以用数组上的 API 操作数据
function fn(a, b, ...args) {
    console.log(a, b, ...args)
}
fn(1, 5, 1, 1, 1, 1)

9、扩展运算符==(能直接展开数组不能直接展开对象)==

// ... 扩展运算符能将 数组 转换为逗号分隔的 参数序列(也就是将数组分隔开),数组的合并、数组的克隆、伪数组转真数组
const boys = ['易烊千玺','王源','王俊凯']
function fn() {
    console.log(arguments);
}
fn(...boys)		// 等同于 fn('易烊千玺','王源','王俊凯'),如果不用扩展运算符收到的将是一整个 数组

// 在对象中用扩展运算符:如果是只有单独一层的话是深拷贝,修改两个对象的值互不影响(地址不一样),如果是有多层结构,只有第一层是深拷贝,里面的数据仍然是浅拷贝(原对象修改,另一对象中的值跟着改变),如果是直接赋值的话是浅拷贝,只是赋值了个地址值过去而已

10、Symbol 类型

符号的用途是 确保对象属性使用唯一标识符,不会发生属性冲突的危险。

1、两创建方式

// Symbol 类型数据并不能做 运算 以及 比较

// 1、创建 Symbol 类型,类型为 symbol,symbol 好比身份证,参数好比姓名,两个是不相等的
let s = Symbol('张三')

// 2、创建 Symbol 类型第二种方式,通过这种方式创建的 symbol 类型,参数相等便相等
let s1 = Symbol.for('张三')
let s2 = Symbol.for('张三')

2、添加 Symbol 类型的属性和方法

// 第一种创建方式:动态传值的方法
let game = { name: '俄罗斯方块' }
let methods = { up: Symbol('up') }
game[methods.up] = function () {
    console.log('添加成功');
}
console.log(game);

// 第二种添加 Symbol 方法,因为是动态值要用 [] 包裹
let youxi = {
    name: '狼人杀',
    [Symbol('say')]: function () {
        console.log('成功发言');
    }
}
console.log(youxi);

3、Symbol 提供了 11 个内置对象

11 个内置对象:都是在特定情景下对特定的对象进行操作(使用方法都是通过一个整体作为对象的一个属性动态设置,固定写法),如:
const arr = [1,2,3]
arr[Symbol.isConcatSpreadable] = false		// 这样这个数组就不能作为 被 拼接 的数组

11、迭代器(for…of)数组,for…in 对象

需要自定义遍历数据的时候,要想到迭代器

Iterator 接口主要供 for…of 消费,原生具备 iterator 接口的数据(可用 for of 遍历)【Array、Arguments、Set、Map、String、TypedArray、NodeList】

// 迭代器工作原理:先给指定数据创建一个迭代器对象,迭代器对象有next方法取数据,需要自定义遍历数据的时候,要想到迭代器
const xiyou =  [1,2,3]
let iterator = xiyou[Symbol.iterator]()
console.log(iterator.next())	// 返 { value:1, done:false } 表示数据没取完,取完value为undefined done值为true

// 自定义遍历数据
const banji = {
    name: '1',
    stus: [1, 2, 3, 4, 5],
    [Symbol.iterator]() {
        // 索引变量控制是否遍历
        let index = 0
        // let _this = this // 如果不是箭头函数要将this指向指回,否则会指向return对象
        return {
            next: () => {
                if (index < this.stus.length) {
                    const result = { value: this.stus[index], done: false }
                    // 下标自增
                    index++
                    return result
                } else {  return { value: undefined, done: true }  }
            }
        }
    }
}
for (const v of banji) {  console.log(v)  }

12、生成器(一个 next 走一段 yield 的代码)

// 生成器就是一个特殊的函数,在关键字和函数名中间加一个 * ,调用后返回一个迭代器对象,有next方法
// 生成器是可以传入实参的
function* gen(args) {	// * 写在左右中间都可以
    console.log(args)
    let y = yield '一只小白兔'
    yield '两只小白兔'
    yield '三只小白兔'
}
let iterator = gen('111')
console.log(iterator.next())	// 输出:111 以及遍历的第一个yield {value:'一只小白兔',done:false}
// next方法是可以传入实参的,从第二个next方法传入的实参将会成为第一个 yield 的返回值,以此类推
console.log(iterator.next('123'))
console.log(iterator.next())
console.log(iterator.next())

案例:这样写出来的生成器就 不需要套用一堆定时器,就不会有 回调地域 的问题

function one() {
     setTimeout(() => {
         console.log('111')
         iterator.next()
     }, 1000)
 }
 function two() {
     setTimeout(() => {
         console.log('222')
         iterator.next()
     }, 2000)
 }
 function* gen() {
     yield one()
     yield two()
 }
 // 调用生成器函数,生成一个迭代器对象,调用next方法,调用后会调用第一个定时器,第一个定时器执行完调用第二个定时器
 let iterator = gen()
 iterator.next()

13、Promise

调用 then 方法,返回结果是 Promise 对象,对象状态由回调函数的执行结果决定
1、如果回调函数中返回的结果是 非 promise 类型的属性状态为成功,返回值为对象成功的值,没有 return 状态也为成功,但值是 undefined
// 在 node 中读取文件时操作,用 promise 的方式就不需要全部套在一起读取
const fs = require('fs')
const p = new Promise((resolve, reject) => {
    fs.readFile('./t1.txt', (err, data) => {
        resolve(data)
    })
})
p.then(value => {
    return new Promise((resolve, reject) => {
        fs.readFile('./t2.txt', (err, data) => {
            resolve([value, data])
        })
    })
}).then(value => {
    return new Promise((resolve, reject) => {
        fs.readFile('./t3.txt', (err, data) => {
            // 将拿到的数据压入前面已经获取的数据
            value.push(data)
            resolve(value)
        })
    })
}).then(value => {
    console.log(value.toString());
})

中断 promise 链

关键问题2中,可以得知,当promise状态改变时,他的链式调用都会生效,那如果我们有这个一个实际需求:我们有5个then(),但其中有条件判断,如当我符合或者不符合第三个then条件时,要直接中断链式调用,不再走下面的then,该如何?
(1) 当使用 promise 的 then 链式调用时, 在中间中断, 不再调用后面的回调函数
(2) 办法: 在回调函数中返回一个 pending 状态的promise 对象
<script>
let p = new Promise((resolve, reject) => {setTimeout(() => { resolve('OK');}, 1000);});
p.then(value => {return new Promise(() => {});})	// 返回一个pending状态的promise对象,有且只有这一个方式
.then(value => { console.log(222);})
.then(value => { console.log(333);})
.catch(reason => {console.warn(reason);});
</script>

promise.then()返回的新 promise 的结果状态由什么决定?

(1) 简单表达: 由 then() 指定的回调函数执行的结果决定
(2) 详细表达:
① 如果抛出异常, 新 promise 变为 rejected(失败), value(值) 为抛出的异常
② 如果返回的是非 promise 的任意值, 新 promise 变为 resolved(成功), value(值) 为返回的值
③ 如果返回的是另一个新 promise, 此 promise 的结果就会成为新 promise 的结果,能接着被 then 作为值接收(状态为成功,值为返回值)

14、Set 集合(值)

// Set 集合的创建	增、删、查、清除
const s = new Set([1, 2, 3, 1, 1, 2])
        console.log(s.size);
        s.add(2)
        s.delete(2)
        console.log(s.has(2))
        s.clear()

15、Map集合(键值对)对象升级版

// Map 集合的创建 	增、删、获取、清除
// 相当于对象的升级版,对象只能用 串 来做键,map 能用对象来做键,值是 二维数组
const m = new Map()
        console.log(m.size);
        m.set('a',1)
	   const key = { school: 'gdmec' }
        m.set(key,[1,2,3])
        m.delete('a')
        console.log(m.get('a'))
       	m.clear()
// map 也实现了 iterator 接口:可以被 for...of 循环遍历
	for( const iterator of m ){
        console.log( iterator )		// 遍历出来的每项都是 键值对
    }

16、类 Class

新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已==(类中所定义的方法已经在局部开启了严格模式)==
1、声明类
2、constructor 定义构造函数初始化==(不是必须要有)==
3、静态成员只能 通过类名访问,不能通过实例访问
4、通过 super 可以继承到父类的参数,等效于 es5 的 Father.call( this, xxx,xxx )
5、重写父类方法只需要在 子类 中用相同方法名覆盖即可
6、class 类中 get 和 set 的使用(可以设置一个不存在的值)
// 1、声明父类
class Father {
    constructor(name) {		this.name = name	}
}

// 继承父类(通过  extends  后在构造器中通过  super  来继承想要继承的属性)
class Son extends Father {
    static n = '123'
    // 2、constructor 定义构造函数初始化(不是必须要有)
    constructor(name) {
        super(name)
    }
    cal() {	console.log(this.name + '触发')	}
    
    // 通过 get set 可以对数据的一个读取和设置
    get price() {
        console.log('读取');
    }
    set price(newvalue) {
        console.log('新值', newvalue);
    }
}
const p = new Son('牛马先生')
console.log( Son.n )	// 只有这样才能访问到类上的静态属性
p.cal()

17、数值与对象的扩展API

Number.EPSILON 是 js 表示的最小精度
Number.isFinite( 123 )		// 检测一个数是否为有限数,返布尔值
	Number.isNaN()	// 检测一个数值是否为 NaN
	Number.parseInt()		Number.parseFloat()	// 转整数和浮点数,遇到英文自动截断
	Number.isInteger()		// 判断一个数是否为整数
	Math.trunc()	// 将数字的小数部分抹掉
	Math.sign()		// 判断一个数是正数(1) 负数(-1) 还是零(0)

Object.is( n1, n2 )		// 和全等 === 的区别在于:is 对于 NaN 的判断是返true,两个值得完完全全相等
Object.assign( o1, o2 )	// 对象合并,同属性后者覆盖前者
Object.setPrototypeOf(obj,props)	Object.getPrototypeOf(xxx)		// 给指定对象原型设置属性和获取指定对象的原型属性

18、模块化

index.html
<script type="module">
    // 通用方式:表示将另一模块中所有导出的代码都封存在变量m1中(三种暴露都可用)
    import * as m1 from './module.js'
    // 通用方式:分布引入,不过默认暴露的写法有所不同
    import { xxx } from './module.js'
    // 因为default是关键字,所以不能用来作为引入时的变量名
    import { default as xxx } from './module.js'
    // 只针对默认暴露可用
    import xxx from './module.js'
script>

<script>
    module.js
    // 1、分布暴露(一个一个暴露)
    export let school = 'gdmec'

    // 2、默认暴露(定义好所有变量和方法。可以定义在default的对象里,键值对写法)
    let school = 'gdmec'
    export default { school }

    export default { 
        school: 'gdmec'
    }

    // 统一暴露(定义好所有变量和方法,统一暴露出去)
    let school = 'gdmec'
    export { school }
script>

19、super

// 注意,super关键字表示原型对象时,只能用在对象的方法之中,用在其他地方都会报错。
const proto = {
    foo: 'hello',
};
const obj = {
    foo: 'world',
    find() {
        return super.foo;	// 只能用在对象的方法之中
    },
};
Object.setPrototypeOf(obj, proto);
console.log(obj.find());	// 输出:hello,super指向当前对象的原型对象

es7新特性:includes、指数操作符

1、includes

Array.prototype.includes:方法用来检测数组中是否包含某个元素,返回布尔值,arr.includes( xxx )

2、指数操作符

用来实现幂运算,等效于 Math.pwo( n1, n2)

es8新特性:async、await、对象方法扩展

async、await

async 修饰在函数前,会得到返回一个 promise 对象,promise 对象的结果由 async 函数执行的返回值决定
await 修饰在带有async的函数中,修饰的右侧表达式一般为promise对象,接收完返回promise的返回值,若失败,要用try...catch捕获处理
		经过第一个await修饰之后后面的代码会变成异步

对象方法的扩展(es10:fromEntries)

Object.keys( obj1 )		// 获取对象所有的键【es5】
Object.values( obj1 )	// 获取对象所有的值【es6】
Object.entries( obj1 )	// 获取对象的键值整合成一个个数组项,可搭配map,方便创建map

Object.fromEntries([
    ['name','gdmec']	// 上着是将对象转换为键值对的map数组,fromEntries 是将二维数组,转换为键值对的对象
])

const m = new Map(Object.entries( obj1 )) 	// 因为map就是由键值对组成的数组
Object.getOwnPropertyDescriptors( obj1 )	// 获取对象的描述对象,如是否可枚举,是否可修改...下边可见
Object.create(null,{
    name:{
        value:'gdmec',
        writable:true
    }
})

题外话:Object.entries( obj ) 和 arr.entries( ) 的区别
Object.entries( obj1 )	// 获取对象的键值整合成一个个数组项,二维数组
// 方法返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对(可以直接通过for...of来遍历这个迭代对象)
// 或者通过返回的迭代对象上的next方法取对应的键值,一次取一个,直到取完
const a = arr.entries()
a.next()

es9新特性:es6的扩展运算符和rest参数都是针对数组的,es9对象也有了自己的扩展运算符和rest参数。针对对象的,用法一样、正则、方向断言

es10新特性:trimStart、trimEnd、flat、flatMap、Symbol的description

str.trimStart() 去除左边空白字符串,另一个同理

flat:将多维数组展开

方法会将一个深层次的数组进行递归遍历,而层次取决于参数,默认是 1Infinity 表示展开任意深度的嵌套数组,将所有嵌套的数组值合并成一个数组返回(默认还会移除空项)
[1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]].flat(Infinity);	  // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// 首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。与 map 连着深度值为 1 的 flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些。
flatMap、近似 map 方法
const arr = [1,2,3]
const result =  arr.flatMap( item => [item * 10] )
console.log(result)		// [ 10,20,30 ]	将本来是多维(多少层都无所谓)数组的数组给运算完展开成一维数组

Symbol的description属性:就是输出 Symbol 的描述信息

let s = Symbol('gdmec')
console.log( s.description )	// 输出:gdmec

es11新特性:私有属性、allSettled与all、matchAll、?. 、动态 import、BigInt、globalThis

私有属性

// 类属性默认情况下是公有的,可以使用 哈希前缀 # 的方式来定义私有类属性,这一隐秘封装的类特性由 JavaScript 自身强制执行。
class Person {
    name
    #age
    constructor(name, age) {
        this.name = name
        this.#age = age
    }
}
const p = new Person('gdmec', 18)
console.log(p.name, p.#age)		// 会报错,并不能访问私有属性,但是可以在类内部通过方法访问修改,在外部调用方法就能访问到

allSettled与all

该方法可以传入多个promise对象,永远返回true,里面存放着一个数组:promise对象的状态和返回值都在其中

前者永远返回true,后者只有全部为true才返回true

// 该方法可以传入多个promise对象,永远返回true,里面存放着一个数组:promise对象的状态和返回值都在其中,与all不同的是all必须全部都为成功才返回,有一个错就返回错误的promise对象
const result = Promise.allSettled([ p1,p2 ])

// 1、通过多个await方式发送多个请求,效率偏低:await之后的代码都会变为异步代码,后一个请求需在前一个请求成功返回后才发送
// const  result1 = await reqCategory(pCategoryId);
// const  result2 = await reqCategory(categoryId);
// 2、一次性发送多个请求,而不是等前面发完请求返回后才发后面的请求,只有都成功了true,才正常处理
const results = await Promise.all([reqCategory(pCategoryId), reqCategory(categoryId)]);

String.prototype.matchAll:匹配所有符合的元素

const result = 字符串.matchAll( 正则 )	// 返回一个迭代器对象:可以用for...of循环

?. 可选链操作符

可以用在形参传入方法时在方法中判定:如果没有该属性最终会返回undefined
function main(config){
    const dbHost = config?.db?.host
    console.log(dbHost)
}
main()		// 最终输出 undefined,如果没有可选链操作符会报错

import 动态加载:和 vue 中路由的懒加载是同个道理的

动态导入模块,可以将关键字称为函数。当以这种方式使用时,它会返回一个promise对象,需要对应资源的时候动态加载资源,可以提高性能

import('./module.js').then((module) => {
    console.log(module)
})

BigInt类型

大整形的数值并不能和普通的整数类型运算,必须一起转为大整形

BigInt是一种内置对象,它提供了一种方法来表示大于 2^53 - 1 的整数。这原本是 Javascript 中可以用 [Number] 表示的最大数字。BigInt 可以表示任意大的整数。

Number.MAX_SAFE_INTEGER 该常量表示在 js 中最大的安全数(253次方-1),Math.pow(2, 53) -12 ** 53 - 1
Number.MAX_VALUE 属性表示在 js 里所能表示的最大数值。
// 两种定义方式
let n = 123n;
let b = BigInt(123);
console.log( typeof n )		// 输出 bigint
console.log( BigInt( Number.MAX_SAFE_INTEGER ) + BigInt(1) )		// 输出 9007199254740992n

globalThis 全局 this,node 中也适用

该 this 始终指向 window

jsonp解决ajax跨域的原理

/*
jsonp解决ajax跨域的原理
  1). jsonp只能解决GET类型的ajax请求跨域问题
  2). jsonp请求不是ajax请求, 而是一般的get请求
  3). 基本原理
   浏览器端:
      动态生成
                    
                    

你可能感兴趣的:(JavaScript,ES6,javascript,es6)