ES6入门之Proxy

Proxy格式:

let target = {}, handler = {};  
let proxy = new Proxy(target, handler);  

---
let obj = {};
let proxy = new Proxy(obj, {
    // ...
})

外界每次通过Proxy访问target 对象的属性时,就会经过 handler 对象,因此,我们可以通过重写handler对象中的一些方法来做一些拦截的操作。

监听属性、参数及监听内容

属性值 监听器参数 监听内容
has (target, prop) 监听 in 语句的使用
get (target, prop, reciver) 监听目标对象的属性读取
set (target, prop, value, reciver) 监听目标对象的属性赋值
deleteProperty (target, prop) 监听 delete 语句对目标对象的删除属性行为
ownKeys (target) 监听 Object.getOwnPropertyName() 的读取
apply (target, thisArg, arguments) 监听目标函数(作为目标对象)的调用行为
construct (target, arguments, newTarget) 监听目标构造函数(作为目标对象)利用 new 而生成实例的行为
getPrototypeOf (target) 监听 Objext.getPrototypeOf() 的读取
setPrototypeOf (target, prototype) 监听 Objext.setPrototypeOf() 的调用
isExtensible (target) 监听 Objext.isExtensible() 的读取
preventExtensions (target) 监听 Objext.preventExtensions() 的读取
getOwnPropertyDescriptor (target, prop)
defineProperty (target, property, descriptor) 监听 Object.defineProperty() 的调用

has

handler.has() 方法可以看作是针对 in 操作的钩子

var p = new Proxy(target, {  
  has: function(target, prop) {  
  }  
});  

-targe,目标对象
-prop,需要检查是否存在的属性
-this绑定到handler对象上
-返回一个boolean值

const p = new Proxy({}, {
    has(target, prop){
        console.log(`Checking "${prop}" is in the target or not`);
        return true;
    }
})

console.log('foo' in p);
// Checking "foo" is in the target or not
// true

约束,违背proxy会抛出一个TypeError:
-如果目标对象的某一属性本身不可被配置,则该属性不能够被代理隐藏
-如果目标对象为不可扩展对象,则该对象的属性不能够被代理隐藏

get

handler.get() 方法用于拦截对象的读取属性操作。

var p = new Proxy(target, {  
  get: function(target, property, receiver) {  
  }  
});  
const obj = {foo: 1};
const p = new Proxy(obj, {
    get(target, prop){
        console.log(`Program is trying to fetch the property "${prop}".`);
        return target[prop];
    }
})

p.foo;  // Program is trying to fetch the property "foo".
p.something;    // Program is trying to fetch the property "something".

约束条件:
-如果要访问的目标属性是不可写以及不可配置的,则返回的值必须与该目标属性的值相同。
-如果要访问的目标属性没有配置访问方法,即get方法是undefined的,则返回值必须为undefined。

set

handler.set() 方法用于拦截设置属性值的操作。

var p = new Proxy(target, {  
  set: function(target, property, value, receiver) {  
  }  
});  

-target,目标对象
-property,被设置的属性名
-value,被设置的新值
-receiver,最初被调用的对象。通常是proxy本身,但handler的set方法也有可能在原型链上或以其他方式被间接地调用(因此不一定是proxy本身)
-this绑定到handler对象上
-返回一个布尔值,返回true代表此次设置属性成功了,如果返回false且设置属性操作发生在严格模式下,那么会抛出一个TypeError

const obj = {};
const p = new Proxy(obj, {
    set(target, prop, value){
        console.log(`Setting value "${value}" on the key "${prop}" in the target object`);
        target[prop] = value;
        return true;
    }
})

p.foo = 1;  
// Setting value "1" on the key "foo" in the target object

约束:
-若目标属性是不可写及不可配置的,则不能改变它的值
-如果目标属性没有配置存储方法,即set方法是undefined的,则不能设置它的值
-在严格模式下,若set方法返回false,则会抛出一个 TypeError 异常

apply

handler.apply() 方法用于拦截函数的调用

var p = new Proxy(target, {  
  apply: function(target, thisArg, argumentsList) {  
  }  
});  

-target,目标对象(函数)
-thisArg,被调用时的上下文对象
-argumentsList,被调用时的参数列表
-this绑定到handler对象
-可以返回任何值

const sum = function(...args){
    return args
            .map(Number)
            .filter(Boolean)
            .reduce((a, b) => a + b);

}

const p = new Proxy(sum, {
    apply(target, thisArg, args){
        console.log(`Function is being called with arguments [${args.join()}] and context ${thisArg}`);
        return target.call(thisArg, ...args);
    }
})

console.log(p(1, 2, 3));
// Function is being called with arguments [1,2,3] and context undefined
// 6

construct

handler.construct()用于来接new操作

var p = new Proxy(target, {  
  construct: function(target, argumentsList, newTarget) {  
  }  
});  

-target,目标对象
-argumensList,构造器参数列表
-newTarget,最初调用的构造函数
-this绑定到handler
-返回一个对象

class Foo{};

const p = new Proxy(Foo, {
    construct(target, args, newTarget){
        return {arguments: args}    // 这里返回的结果会是 new 所得到的实例}
})

const obj = new p(1, 2, 3);
console.log(obj.arguments);  // [1, 2, 3]

约束:
返回值必须是一个对象

猜你喜欢

转载自blog.csdn.net/asd104/article/details/80768886