es6 proxy对象代理

Proxy(代理) 是 ES6 中新增的一个特性。Proxy 让我们能够以简洁易懂的方式控制外部对对象的访问。其功能非常类似于设计模式中的代理模式。

使用 Proxy 的好处是:对象只需关注于核心逻辑,一些非核心的逻辑(如:读取或设置对象的某些属性前记录日志;设置对象的某些属性值前,需要验证;某些属性的访问控制等)可以让 Proxy 来做。从而达到关注点分离,降级对象复杂度的目的。

使用方法

var p = new Proxy(target,handler)

其中,target 为被代理对象。handler 是一个对象,其声明了代理 target 的一些操作。p 是代理后的对象。

当外界每次对 p 进行操作时,就会执行 handler 对象上的一些方法。handler 能代理的一些常用的方法如下:

get:读取
set:修改
has:判断对象是否有该属性
construct:构造函数
...

var target={
    name:'obj'
}
var logHandler={
    get:function(target,key){
        console.log(`${key}被读取`)
        return target[key];
    },
    set:function(target,key,value){
        console.log(`${key}被设置为${value}`)
        target[key]=value;
    }
}
var targetWithLog = new Proxy(target,logHandler);

在上面的 demo 中,

targetWithLog 读取属性的值时,实际上执行的是 logHandler.get :在控制台输出信息,并且读取被代理对象 target 的属性。
在 targetWithLog 设置属性值时,实际上执行的是 logHandler.set :在控制台输出信息,并且设置被代理对象 target 的属性的值。

实现虚拟属性

下面的 demo,虚拟了 fullName 这个属性。

var person={
    firstName:'张',
    lastName:'小白'
}
var proxyedPerson = new Proxy(person,{
    get:function(target,key){
        if(key==='fullName'){
            return [target.firstName,target.lastName].join(' ');
        }
        return target[key];
    },
    set:function(target,key,value){
        if(key==='fullName'){
            var fullNameInfo = value.split(' ');
            target.firstName = fullNameInfo[0];
            target.lastName = fullNameInfo[1];
        }else{
            target[key]=value;
        }
    }
})

实现私有变量

下面的 demo 实现了真正的私有变量。代理中把以 _ 开头的变量都认为是私有的。

var api={
    _secret:'xxxx',
    _otherSec:'bbb',
    ver:'v0.0.1'
}
api = new Proxy(api,{
    get:function(target,key){
        if(key.startsWith('_')){
            console.log('私有变量不能被访问');
            return false;
        }
        return target[key];
    },
    set:function(target,key,value){
        if(key.startsWith('_')){
            console.log('私有变量不能被修改');
            return false;
        }
        target[key]=value;
    },
    has:function(target,key){
        return key.startsWith('_')?false:(key in target);
    }
})

抽离校验模块

下面的 demo 实现了在代理中实现设置属性值前做验证。

function Animal(){
    return createValidator(this,animalValidator)
}

var animalValidator = {
    name:function(name){
        return typeof name==='string';
    }
}

function createValidator(target,validator){
    return new Proxy(target,{
        set:function(target,key,value){
            if(validator[key]){
                if(validator[key](value)){
                    console.log(validator[key](value))
                    target[key]=value;
                }else{
                    throw Error(`Cannot set ${key} to ${values}.Invalid.`);
                }
            }else{
                target[key]=value;
            }
        }
    })
}

var dog = new Animal();
dog.name = 'dog'

源码地址:https://blog.csdn.net/sinat_17775997/article/details/84233822

你可能感兴趣的:(es6 proxy对象代理)