JavaScript 深入理解proxy

丶灬走出姿态 提交于 2020-01-25 03:58:19

语法:let p = new Proxy(target, handler);

参数:

target:用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。

handler:一个对象,其属性是当执行一个操作时定义代理的行为的函数。

 

作用:使用p对象来代理target对象

1.访问p代理对象时(读/写/new等),实际是通过handle对象中的函数操作target对象。

2.p.prototype等于target.prototype,即通过p代理对象,可以访问到target的原型。

 

举例:

1.扩展构造函数的源码

function extend(sup, base) {
  //sup和base都是构造函数的引用,都有prototype属性,prototype中的constructor指向构造函数本身。
  // 获取base.prototype对象的constructor属性的描述符对象:{value: ƒ, writable: true, enumerable: false, configurable: true}
  var descriptor = Object.getOwnPropertyDescriptor(
    base.prototype,"constructor"
  );

  //Object.create(proto, [propertiesObject])返回了一个新对象,带着指定的原型对象(proto)和属性([propertiesObject])。
  base.prototype = Object.create(sup.prototype); // base.prototype指向了sup.prototype

  var handler = {
    // 拦截new命令
    construct: function(target, args) {
      console.log('handle.construct')
      var obj = Object.create(base.prototype); // obj指向了base.prototype,即指向了sup.prototype      
      console.log(Boy.prototype===base.prototype) // true
      this.apply(target,obj,args);
      console.log(this)   //{construct: ƒ, apply: ƒ},表示this指向了handler
      return obj; //返回obj对象
    },
    apply: function(target, that, args) {
      console.log('handele.apply')
      sup.apply(that,args); // this绑定到obj,即指向了base.prototype,并执行sup函数
      base.apply(that,args); // this绑定到obj,即指向了base.prototype,并执行base函数
    }
  };

  var proxy = new Proxy(base, handler); // 创建proxy函数对象来代理base对象,handler对象其属性是当执行一个操作时定义代理的行为的函数。
  console.log(proxy.prototype===base.prototype)  //true

  descriptor.value = proxy; // 将proxy对象赋值给base.prototype的constructor.value
  console.log(descriptor.value)

  Object.defineProperty(base.prototype, "constructor", descriptor); // 重新定义base.prototype的constructor属性的特性,包括constructor.value为proxy
  console.log(base.prototype)

  return proxy;
}

// 创建构造函数Person
var Person = function(name){
  this.name = name // this指向了obj,即obj对象上添加了name属性
};

// 调用extend函数,将Person(函数引用)赋值给sup,将第二个匿名函数引用赋值给base,返回proxy函数对象赋值给Boy
var Boy = extend(Person, function(name, age) {
  this.age = age; // this指向了obj,即obj对象上添加了age属性
});

Boy.prototype.sex = "M";
Boy.prototype.hight = 170;

var Peter = new Boy("Peter", 13); // 调用new时,Peter指向了Boy的prototype,会被proxy的construct拦截,返回了obj对象,包含name和age属性
console.log(Peter)
console.log(Peter.sex);  // "M"
console.log(Peter.name); // "Peter"
console.log(Peter.age);  // 13

 

2.扩展构造函数总结:

1)obj对象的-ptoto-属性指向了base.prototype(即proxy.prototype)

2)base.prototype(即proxy.prototype)有constructor属性和-proto-属性,consturctor.value为proxy,-proto-指向了sup.prototype

3)proxy是一个构造函数,函数内容是二进制代码,不能打印出来

proxy:function () { [native code] } 

[[Handler]]:Object //handler对象

[[Target]]:ƒ (name, age) //base函数

[[IsRevoked]]:false //未撤销

4)proxy.prototype包含height、sex、constructor(代理base函数)和-proto-属性(constructor指向Person构造函数)

proxy.prototype:           //proxy.prototype上有height、sex、constructor属性
hight:170
sex:"M"
constructor:ƒ ()            //由handler、target等组成
  [[Handler]]:Object        //handler对象
  [[Target]]:ƒ (name, age)  //base函数
  [[IsRevoked]]:false       //未撤销
__proto__:
  constructor:ƒ (name)      //Person构造函数
  __proto__:Object       

 

参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!