JavaScript里面的Proxy简单运用

41 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

语法结构

    const proxy = new Proxy(target, handler);
  • target: 要使用 Proxy 包装的目标对象,可以是任何类型的对象,包括原生数组,函数,甚至另一个代理。
  • handler: 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 proxy 的行为。

名词描述

Proxy 用于修改某些操作的默认行为,也可以理解为在目标对象之前增设一层拦截,外部所有的访问都必须先通过这层拦截,因此提供了一种机制,可以对外部的访问进行过滤和修改。这个词的原理为代理,在这里可以表示由它来代理某些操作,译为代理器:

    var target = {label: '演员'};
    var proxy = new Proxy(target, {
        set: function(target, key, value, receiver){
            return Reflect.set(target, key, '我是' + value, receiver);
        },
        get: function(target, key, receiver){ 
            return target[key];
        }
    });
    proxy.label = '峡谷演员'; // 触发set:'我是' + value
    console.log(target); // 触发set: {label: '我是峡谷演员'}

Object.defineProperty 是用于监听属性,而 Proxy 是监听整个对象,通过调用 new Proxy() ,可以创建一个代理用来替代另一个对象被称为目标,这个代理对目标对象进行了虚拟,因此该代理与该目标对象表面上可以被当作同一个对象来对待。代理允许拦截在目标对象上的底层操作,而这原本是JavaScript引擎的内部能力,拦截行为使用了一个能够响应特定操作的函数,即通过Proxy去对一个对象进行代理之后,我们将得到一个和被代理对象几乎完全一样的对象,并且可以从底层实现对这个对象进行完全的监控。

下面我们通过一道常见的面试题(实现 a===1&&a===2&&a===3 为true),来看看 Object.definePropertyProxy 代理的简单运用:

    // Object.defineProperty 定义的是属性
    // 可以实现对于题目的要求
    var  _d = 0;
    Object.defineProperty(window, "a", {
        get:function(){
            return ++_d;
        }
    })
    console.log(a===1 && a===2 && a===3); // true
    
    // proxy 代理的是对象 
    // 因此在调用时实际与题目要求并不太相符
    // 但同样也是一种实现方式
    var _p = 0;
    var proxy = new Proxy(window, {
        set: function(target, key, value, receiver){ 
            return Reflect.set(target, key, value, receiver);
        },
        get: function(target, key, receiver){
            if(key === "a") return ++_p;
            else return window[key];
        }
    });
    console.log(proxy.a===1 && proxy.a===2 && proxy.a===3);  // true