SOURCE

// Proxy
// 语法:let proxy = new Proxy(target, handler)
// target  --   表示所要拦截的目标对象
// handler --   也是一个对象,用来定制拦截行为

let lv = {
    brand:'prada',
    price:9000
}

// ①、get  得到某对象属性值时预处理的方法,可以接收两个常用参数
// target:得到的目标值;
// key:目标的key值,相当于对象的属性
// receiver:一般都是指向proxy实例对象
// 注:如果一个对象属性不可配置(configurable:false)且不可写(writable:false),则proxy不能修改该属性,否则通过对象访问该属性会报错
lv = new Proxy(lv,{
    // 拦截读取属性操作
    get(target,key,receiver) {
      console.log(target,'--->target')  // {"brand":"prada","price":9000},
      console.log(key,'--->key')  //  price
    //  console.log(receiver,'--->receiver')  // lv   proxy实例对象本身
      if(target['brand'] == 'prada') {
          if(target['price']>5000) {
              return '无力支付'
          } else {
              return '可以,马上发货'
          }

      }
    }
})

console.log(lv.price)  //  无力支付


console.log('------------------------------')

// ②、set  用来拦截某个属性的赋值操作,可以接收四个参数
// target:目标值
// key:目标的key值
// value:要改变的值
// receiver:改变前的原始值,一般指 proxy实例对象本身
let arr = []
arr = new Proxy(arr,{
    // 拦截写入的操作
    set(target,key,value,receiver) {
        console.log(target,'--->target')  // []
        console.log(key,'--->key')        // 0
        console.log(value,'--->value')    // 11 
        console.log(receiver,'--->receiver') // [11]   proxy实例对象本身

        if(typeof value == 'number') {
            target[key] = value
            return true  // 成功写入时要返回true
        } else {
          throw new TypeError('不能引入字符串类型的数据')
        }

    }
})
arr.push(11)
// arr.push('11') // Uncaught TypeError: 不能引入字符串类型的数据

console.log(arr.length)  // 1 

// ③、proxy实例可以作为其他对象的原型
let pro = new Proxy({},{
    get(target,key) {
        return 777
    }
})
// pro对象是obj对象的原型,obj本身并没有name属性,所以根据原型链,会在pro对象上读取该属性,导致被拦截读取
let obj = Object.create(pro)
console.log(obj.name)   //  777

console.log('-------------------------------')

// apply 拦截函数的调用、call和apply操作,可以接收三个参数
// target:目标对象
// ctx:目标对象的上下文对象 (this)
// arg:目标对象的参数数组
let fn = ()=> {
    console.log('111')
}
fn = new Proxy(fn,{
    apply(target,ctx,arg) {
        console.log(target,'--->target')
        console.log(ctx,'--->ctx')
        console.log(arg,'--->arg')
      return console.log('call拦截')
    }
})
fn()
// Reflect.apply(...arguments) 直接调用 Reflect.apply也会被拦截
// Reflect.apply(fn, null, [9, 10]) 
console 命令行工具 X clear

                    
>
console