ES6知识点

1. Promise

一种异步编程的解决方案
情景:网络请求时,请求是无法立即拿到结果的,需要等请求返回时,通过回调函数获取请求的结果,如果请求比较复杂,嵌套层级过多,则不利于编程和处理维护等
在这里插入图片描述
Promise可以解决回调地狱问题!!
缺点:不可取消

1.1 基本语法

使用格式:

// Promise接收一个函数作为参数,且函数接收两个函数作为参数,一个为成功的回调,一个为异常的回调
// then接收一个函数作为参数,该函数有参数,表示请求的结果
new Promise((resolve,reject)=>{
	// 异步操作
}).then(res=>{
	// 业务逻辑
}).catch(err=>{
	// 失败逻辑
})

Promise类就是用于封装异步操作的,所以如果存在异步都可以使用其封装。典型的setTimeout

new Promise((res,rej)=>{
	// 异步请求
	setTimeout(()=>{
	// res()和rej()都可以接受参数,前者表示成功,后者表示失败
	// 请求成功会进入到 then() 回调中!
	// 请求失败会进入到 catch() 回调中!
		try{
			res() //成功
		}
		catch(e){
			rej() // 失败
		}
	},1000)
}).then(()=>{
	// 业务处理
	
	// 业务处理完,如果需要根据处理结果发送异步请求,只需要继续返回一个Promise即可
	return new Promise((res,rej)=>{
		setTimeout(()=>{
			res()
		},1000)
}).then(()=>{
	// 其他
}).catch()

注意:返回值为Promise时,可以将将原来的嵌套变成了链式结构!!每个Promise中进行了异步请求,在then中处理了返回结果。
注意:reject可传可不传

特别注意:then入参也可以是两个函数,则前一个为成功的回调,后一个为失败的回调

...
.then(res=>{},err=>{})

当页面切换时,如果后台还处于promise的等待结果状态则会发生错误,如果不想显示出来,想自己处理,则建议使用.catch()处理流程

1.2 Promise三种状态

sync:同步
async:异步

三种状态:

  • Pending:等待
  • Fulfilled:成功,调用resolve(val),然后进入then回调逻辑
  • Rejected:失败,调用reject(val),然后进入catch回调逻辑

注意:在同步代码中使用try{} catch(){} finally{}代码块来捕获错误,在异步函数中使用.catch()回调来捕获异常

1.3 Promise链式调用

第一种方式是1.1中的new Promise然后处理异步操作,在then中处理返回结果
第二种方式是直接使用:Promise.resolve(),这种适用于无需异步操作,只是为了回调then
第三种方式直接return xxx,省略写法,xxx为传递到then中的参数

// 第一种 返回new Promise包裹异步操作,完成链式调用
.then(r=>{
	// 业务操作
	return new Promise(resolve=>{
	// 异步操作
})}).then()

// 第二种,返回Promise.resolve() or Promise.reject(),直接回调then or catch
.then(r=>{
	// 业务操作
	return Promise.resolve(xxx)
}).then()

// 第三种,直接返回参数 or 抛出异常,直接回调then or catch
.then(r=>{
	// 业务操作
	return xxx;
	// throw 'error message'
}).then()

1.4 Promise.all

用于同时请求多个异步,等待所有结果都返回时,再返回结果

  1. 如果都resolve进入then回调,参数是顺序的返回值数组
  2. 如果任何一个reject则进入catch回调,参数是错误信息
    Promise.all接收一个Promise实例的数组,然后.then中参数为返回的结果数组!!按照顺序。
Promise.all([
	new Promise(),
	new Promise()
]).then(resultArr=>{})

1.5 Promise.race

入参和all相同,特殊的是,仅仅返回最先resolve或reject的那个值,可用于控制请求超时:

const timeout = async(time)=>new Promise(resolve=>setTimeout(resolve('请求超时!'),time))
async function test(){
	Promise.race([
		异步请求,
		timeout(2000)
	])
	.then()
	.catch()
}
test()

此时,当异步请求返回时间超过2秒时,timeout函数会先返回!进入then接受到请求超时!

2 ES6中的箭头语法=>

()=>{}:是ES6声明一个函数所使用的语法,同普通函数相比,该语法自动绑定环境中的this,即一层层从内向外查找this

箭头表达式有多种:

(参数1、参数2。。。)=>{函数}
(参数1、参数2。。。)=>表达式
(参数1)=>{函数}
参数1=>{函数}
参数1=>表达式

相当于:var f=function(参数){return 表达式}

注意:展开的函数声明中的this和箭头表达式this不是一个含义,前者代指函数(谁调用指谁),后者代指实例(绑定函数外环境中的this),为了使展开后含义不变,可以在函数闭包外引用this,然后在内部使用新引用变量:

let that=this;
this.timerID=setInterval(function(){return that.tick();},1000);

也可以使用bind进行绑定:函数.bind(调用对象,参数)

bind用法:
bind接收的参数,第一个为函数内部this指向的对象,其后为函数传递的参数
bind返回值为修改了this指向的函数,原函数不变

注意:bind和call和apply区别:bind只会修改指向,不会立即调用

3 export和import和commonJS

import不能存在于动态语句中,如if

3.1 CommonJS

// 导出
module.export = {
	flag: true,
	run(){},
	name: "pp"
}

// 导入
let {flag,run,name} = require('./xxx.js)
// 或
let x = require('./xxx.js)
let flag = x.flag

注意:require()接受两个参数,第一个数组表示所要加载的Javascript文件,第二个是加载完成后所要运行的回调函数。

require([ 
		"script1.js", 
		"script2-a.js", 
		"script2-b.js", 
		"script3.js" 
	], 
	function(){ 
		initScript1(); 
		initScript2(); 
		initScript3(); 
	} 
); 

原生的require()不支持按次序加载,所以到底先加载哪个,无法事前知道,require()只保证这四个文件全部加载完成之后,才会运行所指定的回调函数。
如果按次序加载对你很重要,你可以使用官方提供的order插件。

3.2 ES6 export/import

// 导出:写法1
export let name = 'pp
export let age = 12
// 导出:写法2
let name = "pp"
let age = 213
export {name,age}

// 导入
import {flag,sum} from './xxx.js'
console.log(flag)

// html中使用
<script src="./xxx.js" type="module"></script>

3.2.1 export default

导出默认模块,普通导出:导出的名字和导入的名字必须相同才能正确获取

export default导出则为匿名,可以在导入的时候去自定义名字,一个文件default导出的只能存在一个,导入的时候不需要{},表示导入默认导出项

export default x

import y from 'xxx.js'

3.2.2 统一全部导出

由于对于非default导入需要 保证导入的变量名和导出的相同,当导入变量很多,则可以采用导入全部作为一个变量,然后去使用

// 全部导出
import * as x from 'xxx.js'
console.log(x.name)

3.2.3 同时导出默认和普通模块

import 名称,{xx,xx,xx}  from  模块  // 默认和按需同时导入,默认的必须写在前面

3.2.4 导出模块改名

对于默认导出模块,没有固定名称,导入时进行命名使用,对于普通模块,导入使用时必须和导出名相同,可以使用as进行重命名

import {xx,xx,xx} from  模块文件名字
import {xx as 别名,xx,xx} from  模块文件名字

3.3 es6和commonjs导出区别

  • 在模块导出基本类型数据时,require方式无法获取内部最新数据而且修改变量值会脱钩,import方式外部无法修改模块的数据(只读),但是非默认导出属性可以获取内部最新值。
  • 在模块导出引用类型数据时,外部和内部的修改都可以被观测到!

4 class

class中定义的方法和属性都不可以直接通过类名调用,可以将class代码块看作静态的,无法运行的
class中定义在this上的,属于实例属性,需要初始化才能使用,所有挂载在this上的方法或者属性,在实例上都是会复制一份自己的。
class中的类方法是定义在prototype上,可以通过:类名.prototype.方法()来调用,也可以实例化后通过:实例名.方法()调用

class Person{
  constructor(){
    this.name="pp"
    this.say=()=>{console.log('say')}
  }
  show(){
    console.log('show')
  }
}
var p = new Person()
console.log(p)

在这里插入图片描述
直接在class类的prototype上定义属性和方法可以在所有该类的实例上调用,同时也可在类上通过原型调用,相当于在类中定义类方法

获取实例对象的属性(不包括原型上):Object.getOwnPropertyNames(实例对象)

注意:ES6中将toString改成了不可枚举类型。
注意:类.prototype 而 实例.proto ;这两者等价,在这上面添加属性都会影响所有实例
注意:class 不存在变量提升。

4.1 class的name

定义class有两种方式:

class Person{} // name为Person,可以new Person()获取实例
const P = class Person{} // name为P,可以new P()获取实例,里面的Person相当于无效,可简化
const P = class{} // 效果同上

class的立即执行式:

let person = new class{
	constructor(name){
		this.name=name
	}
}("pp")

4.2 class私有方法

一种方法是用命名区分,前面加上下划线,但是依然可以访问到,另一种是,放到类外部:

//PrivateMethod.js
export default class PrivateMethod{
    // 构造
    constructor() {
    }
    getName(){
        priName();
    }
}
function priName(){
    console.log('私有方法测试');
}

//index.js
import PriMe from './PrivateMethod';
let prime = new PriMe();
prime.getName();

4.3 class静态方法

类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。

class StaticMethod{
	//定义静态方法
	static getAge(){
	 return '获取Age的静态方法';
	}
}
//通过类名直接调用
console.log(StaticMethod.getAge());

如果A继承B,则A的静态方法,可以被B继承。调用父类的静态方法:super(xxx)
说明:静态方法只能在静态方法中调用,不能再实例方法中调用。
ES6中只有静态方法,没有静态属性,如需定义静态属性:A.xxx=xxx这样来定义
ES7中:

//StaticMethod.js
//ES7提案 定义静态属性
static lastName = 'pcaca';
//ES7定义实例属性
height = '150cm'; // 如果不写this,在类中默认定义实例属性

参考:https://blog.csdn.net/pcaxb/article/details/53759637

5 async await

这是一个语法糖用于将异步转换成同步

async用于将一个函数标识为异步函数,他的返回值会被编译器特殊处理,返回成一个Promise对象
await用于暂停标识为异步的函数,直到该函数返回了结果,再继续往下执行代码。

这两个关键字常用于异步回调中:

// 使用then
async function test(){}
test().then().catch()
// 使用async await
try{
  let result = await test()
}catch(e){}

特殊的:如果在多个地方使用await可能使性能下降!

async function(){
	await test();// 假设3秒返回
	await test();// 在前一个3秒返回后,执行当前再等3秒才能返回,总共花费6秒
}

解决办法:将异步函数放在变量中,再await

async function(){
	cosnt t1 = test(); 
	cosnt t2 = test();
	await t1;
	await t2;// 两个同时执行并等待,最终执行时间为3秒
}

6 解构赋值

可以用于结构数组和对象,达到快速赋值的效果:

let a = [1,2,3];
let [x,y,z] = a; // xyz分别赋值为123

let a = {name:'p',age:1}
let {name,age} = a; // name=p age=1

注意:解构赋值,如果所解构的原对象是一维数组或一维对象(对象中属性的值都是基本数据类型),其本质就是对基本数据类型进行等号赋值,那它就是深拷贝;
如果是多维数组或嵌套对象,其本质就是对引用类型数据进项等号赋值,那它就是浅拷贝;
最终的结论就是:解构赋值是浅拷贝(因为它确实不能对多维数组或对象达到深拷贝的作用);

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值