Javascript Proxy对象 简介

Javascript Proxy对象 简介

 

Javascript Proxy对象javascript

 

改变你操做对象的方式java

Proxies 是Javasript对象的中间件函数

...或者说至少是那种很早的版本。this

ES6 中引入Proxies,让你能够自定义Object的基本操做。例如,get就是Object的基础操做方法。spa

const obj = {
   val: 10
};
console.log(obj.val);

这里,console.log()表达式在对象obj上执行get方法来获取val的值。操作系统

另外一个对象的基本操做方法是 set3d

const obj = {
   val: 10
};
obj.val2 = 20;

这里,set方法用来给对象obj设置一个新的值。code

如何建立Proxy?

const proxiedObject = new Proxy(initialObj, handler);

调用Proxy构造函数,new Proxy()将返回一个对象,不只包含了initialObj里的值,并且其基本操做(如getset)如今能够经过handler对象来指定一些自定义逻辑。中间件

咱们写个例子来理解这个概念,对象

const handler = {
    get: function() {
        console.log('A value has been accessed');
    }
}

const initialObj = {
    id: 1,
    name: 'Foo Bar'
}

const proxiedObj = new Proxy(initialObj, handler);

console.log(proxiedObj.name);

如今,若是咱们没有构造一个Proxy对象,执行第14行的console.log(proxiedObj.name)会在控制台输出 “Foo Bar”。

不过如今咱们定义了一个Proxy,并在第三行get方法中定义了一些自定义逻辑。

如今执行console.log(proxiedObj.name)会在控制台输出 “A value has been accessed”。

仔细看,你会发现控制台中实际上有两条记录。 “A value has been accessed” 和 undefined。 为何?

get运算符的默认实现是返回Object中存储的值。因为咱们将它重写为只记录一条语句,该值永远不会返回,所以第14行的console.log()输出undefined

让咱们来解决这个问题!

get运算符有两个参数 - 对象自己和被访问的属性。

const handler = {
    get: function(obj, prop) {
        console.log('A value has been accessed');
        return obj[prop]; // 返回访问的key在obj的值
    }
}

const initialObj = {
    id: 1,
    name: 'Foo Bar'
}

const proxiedObj = new Proxy(initialObj, handler);

console.log(proxiedObj.name);

返回属性值

返回属性值 --- 控制台的输出

 

好多了吧!

咱们为get提供的自定义覆盖被称为“拦截器”(大概基于操做系统拦截的概念)。 handler对象基本上是一个包含一组“拦截”的对象,每当访问对象属性时都会被触发。

咱们给set也添加一个“拦截器”。 咱们将作一样的事情 - 任什么时候候设置一个值,咱们将记录被修改的属性,以及为该键设置的值。

set操做符有三个参数 - 对象自己,被访问的属性和为该属性设置的值。

const handler = {
    get: function(obj, prop) {
        console.log('A value has been accessed');
        return obj[prop];
    },
    set: function(obj, prop, value) {
        console.log(`${prop} is being set to ${value}`);
    }
}

const initialObj = {
    id: 1,
    name: 'Foo Bar'
}

const proxiedObj = new Proxy(initialObj, handler);

proxiedObj.age = 24

添加`set` “拦截器”

这里,在第18行进行的访问将触发第6行定义的功能,该功能将记录正在访问的属性和正在设置的值。

`Set` “拦截器” —— 控制台的输出

一个真实的例子

假设咱们有一个定义叫person的对象

const person = {
   id: 1,
   name: 'Foo Bar'
};

若是咱们想让这个对象的id属性是一个私有属性呢? 没人可以经过person.id访问这个属性,若是有人这样作,咱们须要抛出一个错误。 咱们将如何作到这一点?

让Proxies来拯救吧!‍

咱们所须要作的就是给这个对象建立一个Proxy,并覆盖get运算符来阻止咱们访问id属性!

const handler = {
    get: function(obj, prop) {
        if (prop === 'id') { // Check if the id is being accessed
            throw new Error('Cannot access private properties!'); // Throw an error
        } else {
            return obj[prop]; // If it's not the id property, return it as usual
        }
    }
}

const person = {
    id: 1,
    name: 'Foo Bar'
}

const proxiedPerson = new Proxy(person, handler);

console.log(proxiedPerson.id);

阻止访问私有属性

这里,在咱们给get建立的“拦截器”,咱们检查被访问的属性是不是id属性,若是是的话,咱们会抛出一个错误。 不然,咱们照常返回值。

私有属性 — 控制台输出

另外一个极好的用例是校验。 经过设置set“拦截器”,咱们能够在设置值以前添加自定义验证。 若是该值不符合验证,咱们能够抛出一个错误!

const handler = {
    set: function(obj, prop, value) {
        if (typeof value !== 'string') {
            throw new Error('Only string values can be stored in this object!');
        } else {
            obj[prop] = value;
        }
    }
}

const obj = {};

const proxiedObj = new Proxy(obj, handler);

console.log(proxiedObj); // This will log an empty object
proxiedObj.name = 'Foo Bar'; // This should be allowed
console.log(proxiedObj); // This will log an object with the name property set

proxiedObj.age = 24; // This will throw an error.

自定义对象的属性校验

自定义校验 - 控制台输出

在上面的例子中,咱们已经看到了getset“陷阱”。 实际上能够设置更多的“陷阱”。 你能够在这里找到整个列表

Proxy对象只是在阅读关于它们的这篇文章以后才进入个人视野,我已经能够在我天天写的代码中看到它们的用处了!

相关文章
相关标签/搜索