语法: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