文章目录
- 1. Reflect
- 1.1 代替Object 的某些方法
- 1.2 修改某些Object 方法返回结果
- 1.3 命令式变为函数行为
- 1.4 ! 配合Proxy
- 2. ! Promise
- 2.1 回调地狱
- 2.2 Promise 使用
- 2.3 Promise 对象的状态
- 2.4 解决回调地狱的方法
- 2.5 Promise.all
- 2.6 Promise.race
- 3. Generator 函数
- 3.1 基本语法
- 3.2 手动版本函数
- 3.3 自动版本函数
- 4. Class 语法
- 4.1 类的写法
- 4.2 get() / set() 拦截用法
- 4.3 类的静态属性和方法
- 5. Class 继承
- 5.1 基本语法
- 5.2 利用面向对象思想渲染页面
1. Reflect
Reflect可以用于获取目标对象的行为,它与Object类似,但是更易读,为操作对象提供了一种更优雅的方式。它的方法与Proxy是对应的。
1.1 代替Object 的某些方法
比如object.defineProperty()
let obj = {}
Reflect.defineProperty(obj,"name",{
value:"kerwin",
writable:false,
enumerable:false
})
console.log(obj)
两者唯一不同的地方是返回Boolean 值。
1.2 修改某些Object 方法返回结果
简单了解就行,面试有时会问。
//老写法
try{
object.defineProperty(target,property,attributes)};
// success
catch (e){
// fail
}
//新写法
if (Reflect.defineProperty(target,property,attributes)){
// success
else{
// fail
}
使用Reflect 的好处:在处理异常错误时不需要try…catch ,只会判断true / false,这样不会打断程序。
1.3 命令式变为函数行为
const obj = {
name:"kerwin"
};
// 老写法
console.log("name"in obj)//true
//新写法
console.log(Reflect.has(obj,'name'))//true
}
// 老写法
delete (obj.name)
// 新写法
Reflect.deleteproperty(obj,"name")
1.4 ! 配合Proxy
之前使用Proxy:
let s = new Set()
let proxy = new Proxy(s,
get(target,key){
//判断如果key 是方法,修正this指向
let value = target[key]
if(value instanceof Function){
//call apply bind
return value.bind(target)}
return value
},
set(){
console.log("set")
})
Reflect 配合 Proxy 使用:
Let s = new Set()
Let proxy = new Proxy(s,
get(target,key){
//判断如果key 是方法,修正this指向
//target[key]
Let value = Reflect.get(target,key)
if (value instanceof Function){
//call apply bind
return value.bind(target)
}
return value
},
set(target,key,value){
Reflect.set(...arguments)
}
})
使用Reflect 可以拿到代理对象的默认行为
Proxy 代理数组非常在行!
let arr = [1,2,3]
Let proxy new Proxy(arr,{
get(target,key){
console.log("get",key)
return-Reflect.get(...arguments)
},
set(){
return Reflect.set(...arguments)
}
})
Reflect 不仅能拦截数组的push() 等方法,而且能拦截无压抑的检测数组长度的改变
2. ! Promise
Promise是异步编程的一种解决方案,比传统的解决方案回调函数更合理和更强大。ES6将其写进了语言标准,统一了用法,原生提供了Promise对象。
- 指定回调函数方式更灵活易懂。
- 解决异步回调地狱的问题。
2.1 回调地狱
回调地狱,其实就是回调函数嵌套过多导致的
·当一个回调函数嵌套一个回调函数的时候
·就会出现一个嵌套结构
·当嵌套的多了就会出现回调地狱的情况
- 比如我们发送三个ajax请求
- 第一个正常发送
- 第二个请求需要第一个请求的结果中的某一个值作为参数
- 第三个请求需要第二个请求的结果中的某一个值作为参数
ajax("/aaa",function (data)
console.log(data)
ajax("/bbb",function (data)
console.log(data)
ajax("/ccc",function (data)
console.log(data)
}function (
})
}function ()
})
}function ()
)
当代码成为这个结构以后,已经没有维护的可能了。
2.2 Promise 使用
使用Promise 处理异步任务时我们首先先new 一个Promise 构造函数,其中写入一个执行器函数(后面程序按什么情况执行就看执行器函数)
补充:then()方法是异步执行。
意思是:就是当.then()前的方法执行完后再执行then()内部的程序,这样就避免了,数据没获取到等的问题。
语法:promise.then(onCompleted, onRejected);
参数
promise必需。Promise 对象。
onCompleted必需。承诺成功完成时要运行的履行处理程序函数。
onRejected可选。承诺被拒绝时要运行的错误处理程序函数。
- 第一种使用方法
let pro = new Promise(function(resolve,reject){
//执行器函数
setTimeout(()=>{
reject()
},1000)
})
pro.then(()=>{
console.1og("奖金")
},()=>{
console.1og("没有")
})
- 第二种使用方法
pro.then((res)=>{
console.1og("奖金",res)
}).catch((err)=>{
console.1og("没有",err)
2.3 Promise 对象的状态
这一块内容在面试时非常重要!
Promise对象通过自身的状态,来控制异步操作。Promise实例具有三种状态。
- 异步操作未完成 (pending)
- 异步操作成功 (fulfilled)
- 异步操作失败 (rejected)
这三种的状态的变化途径只有两种。
- 从“未完成”到“成功”
- 从“未完成”到“失败”
一旦状态发生变化,就凝固了,不会再有新的状态变化。这也是Promise这个名字的由来,它的英语意思是“承诺”,一旦承诺成效,就不得再改变了。这也意味着,Promise实例的状态变化只可能发生一次。
因此,Promise的最终结果只有两种。
- 异步操作成功,Promise实例传回一个值(value),状态变为fulfilled。
- 异步操作失败,Promise实例抛出一个错误(error),状态变为rejected。
2.4 解决回调地狱的方法
- .then.then 链式调用
let pro = new Promise(function(resolve,reject){
//执行器函数
setTimeout(()=>{
reject()
},1000)
})
pro.then((res)=>{
console.1og("奖金1",res)
//如果return非promise类型,pending-fulfilled
// 如果return promise类型,根据这个新的promise对象的结果,决定
// pending-fulfilled pending-rejected
return res
}).then((res)=>{
console.1og("奖金2",res)
})catch((err)=>{
console.log("没有",err)
})
2.5 Promise.all
let pro1 = new Promise(function(resolve,reject)
//执行器函数
setTimeout(()=>
resoLve(1000)
},1000)
})
let pro2 = new Promise(function(resolve,reject)
//执行器函数
setTimeout(()=>
resoLve(2000)
},2000)
})
let pro3 = new Promise(function(resolve,reject)
//执行器函数
setTimeout(()=>
resoLve(3000)
},3000)
})
Promise.all([pro1,pro2,pro3]).then(res=>{
// 例如对hideloading的处理
console.log(res)
}).catch(err=>{
console.log(err)
})
等到pro1,pro2,pro3 都有结果了之后再去打用相应的回调。
2.6 Promise.race
let pro1 = new Promise(function(resolve,reject)
//执行器函数
setTimeout(()=>
resoLve(1000)
},1000)
})
let pro2 = new Promise(function(resolve,reject)
//执行器函数
setTimeout(()=>
resoLve(2000)
},2000)
})
let pro3 = new Promise(function(resolve,reject)
//执行器函数
setTimeout(()=>
resoLve(3000)
},3000)
})
Promise.race([pro1,pro2,pro3]).then(res=>{
// 例如对hideloading的处理
console.log(res)
}).catch(err=>{
console.log(err)
})
无论pro1,pro2,pro3 哪一个有结果了,程序就会执行对应的回调。
这一般是开发时将程序连接在三个服务器上,如果有服务器瘫痪,但只要有一个服务器健在就可以接收到数据,完成程序的执行。
我们也可以用这个来做服务器超时处理,因为Promise.race 是谁快执行谁。
3. Generator 函数
Generator函数是ES6提供的一种异步编程解决方案
Generator函数是一个状态机,封装了多个内部状态。
执行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历Generator函数内部的每一个状态。
用同步代码去编程异步代码
3.1 基本语法
// * 在function 后面或者 gen后面或者两者之间都可以
function *gen(){
console.log(11)
yield "aaa"//产出
console.log(22)
yield "bbb"
console.1og(33)
Let g gen()
g.next()
g.next()
g.next()
// 11
// 22
// 33
函数遇到yeild 会停止执行下面的代码,只有使用next() 才可以向下执行一步。
g.next() 就是yeild 产出的值
let res1 = g.next()
console.log(res1)
let res2 = g.next()
console.log(res2)
let res3 = g.next()
console.log(res3)
// return ...
对g 进行遍历得到的结果是
// aaa
// bbb
如果函数中存在return 语句,for…of 循环不会遍历得到return 的结果,因为res3 = {value: ‘ccc’,done: true},根据迭代器的知识判断为true 时程序就停止了,不会得到return 的值。
3.2 手动版本函数
function ajax(url){
return new Promise((resoLve,reject)=>{
Let xhr new XMLHttpRequest()
xhr.open("get",url,true)
xhr.send()
xhr.onreadystatechange function(){
if(xhr.readystate===4){
if(xhr.status>=2008&xhr.status<300){
resoLve(JSON.parse(xhr.responseText))
}else{
reject(xhr.responseText)
}
function *gen(){
Let res yield ajax("1.json")
console.log("第一个请求的结果",res)
Let res2 yield ajax("2.json",res)
console.1og("第一个请求的结果",res2)
Let g gen()
//手动版本
/console.1og()
g.next().value.then(data=>{
/console.log(data)
g.next(data).value.then(res=>{
g.next(res)
})
3.3 自动版本函数
自动版本函数必须保证产出的是一个Promise 对象。
function AutoRun(gen)
Let g gen();
function next(data)
Let res g.next(data);
if (res.done)return
res.value.then(function (data){
next(data);
});
next();
}
AutoRun(gen)
4. Class 语法
4.1 类的写法
传统构造函数写法:
function Person(name,age){
this.name = name
this.age = age
// prototype 原型
Person.prototype.say function(){
console.log(this.name,this.age)
Let obj = new Person("kerwin",100)
console.log(obj)
ES6写法:
本质上还是传统函数原型
cLass Person{
constructor(name,age){
this.name = name
this.age = age
}
say(){
console.log(this.name,this.age)
Let obj = new Person("kerwin",100)
console.log(obj)
4.2 get() / set() 拦截用法
cLass Person{
constructor(name,age,location){
this.name = name;
this.age = age;
this.location = location
get location(){
console.log("get")
// return this.location
}
set location(data){
console.log("set",data)
let obj = new Person("kerwin",100,"dalian")
get() 存在return 语句会得到下图所示结果:
set() 中添加this.location = data 会得到下图所示效果:
给obj 设置以下操作可恶意使访问obj.html 就可以在html 中生成DOM节点
{
get html(){
return this.ele.innerHTML
}
set html(data){
this.ele.innerHTML = data.map(item=>`<li>${item}</li>`).join
(")}
}
Let obj = new Person("kerwin",100,"list")
4.3 类的静态属性和方法
cLass Person{
// 现在的写法:静态属性和方法
static myname = "person类的名字"
static mymethod = function(){
// console.log("mythod",this.age
}
constructor(name,age){
this.name = name
this.age = age
say(){
console.log(this.name,this.age)
}
// 以前的写法:
// Perpson.myname="person类的名字"
// Person.mymethod function(){
// console.log("mymethod")
// }
5. Class 继承
5.1 基本语法
cLass Student extends Person{
constructor(name,age,score){
super(name,age) // 必写
this.score = score}
}
let obj = new Student("kerwin",100,150)
父类方法的继承:
使用super关键字。
父类和子类中含有相同的方法时(子类方法会覆盖父类方法)实行就近原则,即一般情况下输出子类代码。
子类中含有和父类相同的代码部分,可以通过super关键字进行调用,再添加子类自己的代码。
say(){
super.say()
console.log(this.score)
}
父类中的静态属性和方法也会被子类继承,子类中重新设置相同的属性和方法会覆盖父类数据。
5.2 利用面向对象思想渲染页面
<div class="box1">
<h1></h1>
<u1></u1>
</div>
<script>
var data1 =
title:"体育",
1ist:["体育-1","体育-2","体育-3"]
cLass CreatBox{
constructor(select,data){
this.ele = document.querySelector(seLect)
this.titie = data.title
this.list = data.list
this.render()
}
render(){
let oh1 = this.ele.querySelector("h1")
let oul = this.ele.querySelector("ul")
oh1.innerHTML = this.title
oul.innerHTML = this.list.map(item=>
`<1i>${item}</1i>`
).join("")
}
}
new CreatBox(".box1", data1)
</script>
var data2 = {
title:"综艺",
url:"1.png",
1ist:["综艺-1","综艺-2","综艺3"]
}
cLass createlmgBox extends creatBoxt
constructor(seLect,data){
super(seLect,data)
this.imgUrl = data.url
}
render(){
super.render()
let oimg = this.ele.querySelector("img")
oimg.src=this.imgUrl}
}
new CreateImgBox(".box2",data2)
效果展示: