数据劫持升级

56 阅读5分钟

1. 数据劫持升级

let obj = {
  name:'张三',
  age:18
}
let newObj = {}
Object.defineProperties(newObj,{
  name:{
    get(){ // 有人获取obj.name会触发
      return obj.name
    },
    set(val){ // 有人修改obj.name会触发
      obj.name = val
    }
  },
  age:{
    get(){
      return obj.age
    },
    set(val){
      obj.age = val
    }
  }
}) 

2. 数据劫持升级(自己劫持自己)

let obj = {
  name:'张三',
  age:18
}
for(let key in obj){
  Object.defineProperties(obj,{
    ['_' + key] : {
      value: obj[key],
      writable:true
    },
    [key]:{
      get(){
        return obj['_' + key]
      },
      set(val){
        obj['_' + key] = val
      }
    }
  })
}

3. 数据代理(数据劫持)

  1. ES6新增的内置构造函数

  2. 代码:const newObj = proxy(obj,{get(target,key){return target[key]},set(target,key,val){target[key] = val}})

let obj = {
  name:'张三'age:18
}

const newObj = new proxy(obj,{ // 这个obj位置是要劫持的对象
  get(target,key){
    return target[key]
  },
  set(target,key,val){
    target[key] = val
    return true // 如果修改简单数据类型需要加一个这个
  }
})

obj.num = 100 // 此时会触发set(),这就是数据代理与数据劫持的差别
//target:当前代理的对象
//key:这个跟调用的值有关系
console.log(newObj.name) // 此时函数代理get()中第二个参数是name

4. 回调函数

  1. 条件: * 将函数A以实参的形式传递给函数B * 在函数B内以形参的形式调用函数A * 此时函数A就是函数B的回调函数

  2. 回调地狱 * 极其不利于阅读与维护,但是功能没有任何影响 * 封装异步代码很麻烦 ```js function fn(chenggong, shibai) { const num = Math.random() * 3000 + 3001 // 书写一个随机数, 用于倒计时器的等待时间

       setTimeout(() => {
           // 根据 num 的值决定当前是成功还是失败
           if (num > 3000) {
               console.log('网络请求超时, 购买失败', num)
               shibai()
           } else {
               console.log('购买成功', num)
               chenggong()
           }
       }, num)
    

    } fn(() => { console.log('执行成功后, 打印这个内容') }, () => { fn( () => { console.log('第二次买水成功, 打印这个内容') }, () => { console.log('第二次买水失败, 打印这个内容') fn( () => { console.log('第三次买水成功') }, () => { console.log('第三次买水失败') } ) } ) }) ```

5. promise

  1. 作用:解决回调地狱(是一种异步代码的封装方法)
promise其实就是一个盒子,内部放了一些异步代码
  1. promise的三种状态 * 持续(正在运行):pending * 运行成功:fulfilled * 运行失败:rejected * 注意:promise只会从持续转为成功,或者从持续转为失败 ```js let p = new Promise(function (chenggong, shibai) { const num = Math.random() * 3000 + 1500 // 书写一个随机数, 用于倒计时器的等待时间

           setTimeout(() => {
               // 根据 num 的值决定当前是成功还是失败
               if (num > 3000) {
                   console.log('网络请求超时, 购买失败', num)
                   shibai()
               } else {
                   console.log('购买成功', num)
                   chenggong()
               }
           }, num)
       })
    

    // promise支持链式调用 p.then(function(){ // then 指向第一个形参返回的事 console.log('成功') }).catch(function(){ // catch 指向第二个形参返回的事 console.log('失败') }) ```

  2. 封装promise js fn().then(()=>{ console.log('') return fn() }).then(()=>{ console.log('') }).catch(()=>{}) ```js function fn(){ return new Promise( (chenggong, shibai)=> { const num = Math.random() * 3000 + 1500 // 书写一个随机数, 用于倒计时器的等待时间

         setTimeout(() => {
             // 根据 num 的值决定当前是成功还是失败
             if (num > 3000) {
                 console.log('网络请求超时, 购买失败', num)
                 shibai()
             } else {
                 console.log('购买成功', num)
                 chenggong()
             }
         }, num)
     })
    

    } fn().then(()=>{ console.log('第一次成功') return fn() }).then(()=>{ console.log('第二次成功') return fn() }).then(()=>{ console.log('第三次成功') return fn() }).then(()=>{ console.log('第四次成功') return fn() }).then(()=>{ console.log('第五次成功') return fn() }).catch(()=>{ console.log('上述某一次失败了,我都可以捕获到') }) ```

6. async 和 await

  1. 作用:将异步代码书写的跟同步代码一样

  2. 需求: * 需要结合一个函数 * 需要结合一个promise对象

  3. 弊端:不能捕获到promise的错误状态,一旦promise返回的是错误信息,那么会报错阻断程序的运行 * async和await不能捕获到promise的错误状态,但是可以捕获到promise的成功状态

  4. 解决方法: * 封装的 promise 不在返回 失败状态, 永远返回一个成功状态,所以为了区分这次的状态到底是成功了还是失败了, 需要在返回的信息上做一些修改 * 返回的信息是目前开发中比较常用的一个标准,返回一个对象, 内部的 code 属性代表当前是成功还是失败, 成功值为1, 失败值为0,第二个属性的属性名, 不确定, 但是代表的是这个请求的一些信息

  5. 解决方法 * try...catch * 改变 promise 的封装, 不在返回一个失败状态, 永远返回成功状态 ```js function myPro() { const p = new Promise(function (res, rej) { // 书写 异步代码 const num = Math.random() * 3000 + 2000 setTimeout(() => { if (num > 3000) { // console.log('网络请求超时, 购买失败', num) // rej('当前请求超时, 可能是用户电脑网线问题') res({ code: 0, info: '当前请求超时, 可能是用户电脑网线问题' }) } else { // obj 为 模拟的一个数据 const obj = { id: 1, name: '电视机', info: { width: 2, height: 1 } } // console.log('购买成功', num) res({ code: 1, info: obj }) } }, num) })

       return p
    

    }

    async function fn() { const res = await myPro() if (res.code === 0) { // 处理一些 请求失败要做的事 console.log(res.info) } else { // 处理一些请求成功要做的事 console.log(res.info) }

       const res1 = await myPro()
       console.log(res1.code)
    

    }

    fn() ```

7. promise的一些方法

  1. finally(function(){}) * 定义:请求完毕后执行的一些事情

  2. Promise构造函数上的一些方法 * promise.all([需要书写一些promise实例化对象]) js Promise.all([]).then(function(){}).catch(function(){}) // 都成功的时候会执行或者有一个失败的时候会执行 * Promise.race([需要书写一些promise实例化对象]) js Promise.race([]).then(function(){}).catch(function(){}) // 传递的Promise对象中第一个结束的状态为成功时执行,第一个结束的状态为失败时执行 * Promise.allSettled([需要书写一些promise实例化对象]) js Promise.allSettled([]).then(function(){}).catch(function(){}) // 会把Promise所有运行的结果都打印出来,打印成数组形式 * Promise.resolve([需要书写一些promise实例化对象]) js promise.resolve([]).then(function(){}).catch(function(){}) // 一定会返回一个为成功状态的对象,catch一定不会执行 * Promise.reject([需要书写一些promise实例化对象]) js promise.reject([]).then(function(){}).catch(function(){}) // 一定会返回一个为失败状态的对象,then一定不会执行