目录
目录
Proxy与Object.defineProperty()区别
Promise是什么:
promise是解决回调地狱的一种异步编程解决的方案
promise可以理解为一个容器,容器内已经预设好了事件成功和失败的结果。
从语法上说,promise是一个对象,从它可以获取异步操作消息。
·promise有两个特点:
1. 对象状态不受外界影响,promise有三种状态:
pending 进行中
fulfilled 已成功
rejected 已失败
只有异步操作的结果可以决定当前是什么状态,任何其他操作均无法改变这个状态,这也是 promise名字由来,它的英文意思就是“承诺”,其他手段无法改变
2.一旦状态确定,不会改变,任何时候就是此结果。promise对象状态改变只有两个可能:
pending ->fufilled 和 pending ->rejected
只要这两种情况发生,状态凝固,不会改变,此时成为serolved(已定型),改变发生后 对promise添加回调,会立刻得到这个结果
Promise基本用法:
// 基本用法
// promise是一个构造函数,用来生成promise实例
// promise作为构造函数,接收两个参数:resolve 和 reject,它们由js引擎提供,不用自己部署
let promise = new Promise((resolve,reject)=>{})
// resolve函数作用是将promise从pending转变为resolved,在异步成功操作后调用,并将异步成功结果作为
// 参数传递出去
// reject函数作用是将promise从pending转变为rejected,在异步操作失败后调用,将异步报错结果作为
// 参数传递出去
let promise1 = new Promise((resolve,reject)=>{
if(异步操作成功){
resolve('success') //异步成功操作后调用,并将异步成功结果作为参数传递出去
}else{
reject('error') //异步操作失败后调用,将异步报错结果作为参数传递出去
}
})
//promise实例生成后,可以用then方法分别指定 resolved状态 和reject状态的 回调函数
//promise1.then()
//then方法可以接收里昂个回调函数作为参数,第一个是promise对象状态变成resolved,第二个是rejcet,
//其中第二个函数是可选的,非必须
promsie1.then((res)=>{},error=>{})
使用Promise实现Ajax
//使用Promise实现Ajax
const request = (type, url, data = null) => {
const promise = new Promise((resolve, reject) => {
const xmlHttp = new XMLHttpRequest()
xmlHttp.open(type, url)
if (type === 'GET') {
xmlHttp.send()
} else {
xmlHttp.setRequestHeader('Content-type', 'application/json')
xmlHttp.send(JSON.stringify(data))
}
xmlHttp.responseType = 'json'
xmlHttp.onreadystatechange = function () {
/* @0 - (未初始化)还没有调用send()方法
1 - (载入)已调用send()方法,正在发送请求
2 - (载入完成)send()方法执行完成,已经接收到全部响应内容
3 - (交互)正在解析响应内容
4 - (完成)响应内容解析完成,可以在客户端调用了 */
if (xmlHttp.readyState !== 4) return
if (xmlHttp.status === 200){
resolve(xmlHttp.response)
}else{
resject('error')
}
}
})
return promise
}
promise可以实现链式调用
需求背景:当下一个请求需要上一个请求成功后的某个值当参数时
链式调用,then时promise实力上的一个方法。当第一个请求成功时,promise状态为resolve(成功),成功return出第二个请求,然后第二个then方法调用第二个请求,以此类推。如果某个return的请求再then后失败,则会中止该then之后的then调用
query: function (){
request('get',`${this.url}/getOne`)
.then(res => {
//第一次调用成功后,返出第二个请求
const { id ,type} = res ;
if(type==='S'){
return request('get',`${this.url}/getTwo?id=${id}`)
}
})
.then(res => {
const { age, type } = res
if(type==='S'){
//第而次调用成功后,返出第三个请求
return request('get',`${this.url}/getThree?age=${age}`)
}
})
.then(res => {
console.log(res)
})
}
Promise还可以并行调用
并行调用有两个方法,分别是Promise.all()和Promise.race()
Promise.all(),一次性发起所有请求,通过.then可以查看请求的所有结果,当所有请求成功时,Promise状态变为成功(fufilled)then可以查看所有请求成功的结果;当有某一个是失败(rejected),Promise状态变为失败,返回第一个失败的结果
Promise.race(),一次性发起所有请求,但是只能看到一个结果,这个结果的条件是:谁请求最快,就展示谁的,并将状态定义为这个结果的状态
//Promise.all
Promise.all([
request('get',`${this.url}/getOne`),
request('get',`${this.url}/getTwo`),
request('get',`${this.url}/getThree`),
]).then(([a,b,c])=>{
console.log(a,b,c)
})
//Promise.race
Promise.race([
request('get',`${this.url}/getOne`),
request('get',`${this.url}/getTwo`),
request('get',`${this.url}/getThree`),
]).then(a=>{
console.log(a )
})
Proxy-代理
可以理解为在目标对象之前架设一层拦截,外部所有的访问都必须先通过这层拦截,因此提供了一种机制,可以对外部的访问进行过滤和修改。这个词的原理为代理,在这里可以表示由它来“代理”某些操作,译为“代理器”。其作用体现在三个方面:
1.拦截和监视外部对对象的访问
2.降低函数或类的复杂度
3.在复杂操作前对操作进行校验或对所需资源进行管理
注意: 代理对象可以理解为明星的经纪人。(如下所示)
代理模式的逻辑
//声明女孩
var girl = function(name) {
this.name = name
}
//声明男孩
var boy = function(girls) {
this.girls = girls;
this.sendFlower = function(flower) {
return console.log(`hi${girl.name}:男孩送你一个礼物${flower}`)
}
}
//声明代理女孩的 角色
var proxyObj = function(girls) {
this.girls = girls;
this.sendFlower = function(flower) {
(new boy(girls)).sendFlower(flower)
}
}
// 代理实例化
var proxy = new proxyObj(new girl('小美'))
console.log(proxy)
var a = proxy.sendFlower('9999玫瑰花')
ES6 的proxy代理
ES6原生提供了Proxy构造函数,用来生成Proxy实例。
let target = { /*目标对象的属性*/ }; //目标对象
let handler = { /*用来定制拦截操作*/ }; //拦截层对象
let proxy = new Proxy(target, handler);
Proxy 对象的所有用法,都是上面这种形式,不同的只是handler参数的写法(所要使用的功能不同,写法不同)。
new Proxy()表示生成一个Proxy实例,作为代理对象;
target表示所要拦截的目标对象;
handler声明了代理 target 的指定行为,表示一个用来定制拦截行为的对象。handler有十三种方法如下:
get(target, propKey, receiver):拦截对象属性的读取,比如proxy.foo和proxy['foo']。 set(target, propKey, value, receiver):拦截对象属性的设置,比如proxy.foo = v或proxy['foo'] = v,返回一个布尔值。 has(target, propKey):拦截propKey in proxy的操作,返回一个布尔值。 deleteProperty(target, propKey):拦截delete proxy[propKey]的操作,返回一个布尔值。 ownKeys(target):拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、 Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名, 而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。 getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。 defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。 preventExtensions(target):拦截Object.preventExtensions(proxy),返回一个布尔值。 getPrototypeOf(target):拦截Object.getPrototypeOf(proxy),返回一个对象。 isExtensible(target):拦截Object.isExtensible(proxy),返回一个布尔值。 setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。 apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。 construct(target, args):拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。
Proxy与Object.defineProperty()区别
Proxy:
优点:可以劫持整个对象,并返回一个新得对象,有13中劫持操作
缺点:兼容性不好
Object.defineProperty()
优点:可以更好的拦截
缺点:无法监听数组下标的变化,导致直接通过数组下标设置值,不能实时响应( 虽说对常用方法进行了处理,但依然有局限性);只能劫持对象属性,因此需要对每个对象的每个属性进行遍历。
class类
省流:ES6的class可以看作是一个语法糖,它的绝大部分功能ES5同样可以实现
ES5实现:
function setClass {
this.x = x
this.y = y
}
setClass.prototype.eat = function(){
return this.x
}
var f = new setClass('鱼',20)
ES6实现:
class Person{
constructor(name,age) {
this.name=name;
this.age=age
}
action(){
return this.name
}
goTo(){
...
}
}
ES6的calss继承方式:
//class的继承 extends关键字实现
class newPerson extends Person {
constructor(args) {
//super相当于是person.prototype.constructor.call(this)的实现
//super作为函数调用时,代表父类的构造函数,ES6要求,子类的构造函数必须执行一次super
super(args)
const {
name,
age
} = args
this.name = name
this.name = name
}
}