Javascript Proxy对象 简介

更新日期: 2017-12-28阅读: 3.3k标签: proxy

ES6 中引入Proxies,让你可以自定义Object的基本操作。例如,get就是Object的基础操作方法。

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

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

另一个对象的基本操作方法是 set。

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

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


如何创建Proxy?

const proxiedObject = new Proxy(initialObj, handler);

调用Proxy构造函数,new Proxy()将返回一个对象,不仅包含了initialObj里的值,而且其基本操作(如get 和 set)现在可以通过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.
自定义对象的属性校验


自定义校验 - 控制台输出

在上面的例子中,我们已经看到了get和set“陷阱”。 实际上可以设置更多的“陷阱”。 你可以在这里找到整个列表

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

如果你之前在项目或工作中使用过Proxies,我很乐意听到!

~最后~


如果您觉得这篇文章对您有用,请点个赞!

在什么地方卡住了,需要更多的帮助,还是只想打个招呼? 在Hashnode 给我直接发问题,或者在Twitter上Call我。 你也可以在Github上找到我。

来源:原文来源翻译来源

链接: https://www.fly63.com/article/detial/291

js_es6中对象代理proxy用法实例浅析

ES6中提出了一个新的特性,就是proxy,用来拦截在一个对象上的指定操作。这个功能非常的有用。每当代理对象被赋值,处理器函数就会调用,这样就可以用来调试某些问题。

拿Proxy可以做哪些有意思的事儿

Proxy是什么意思?Proxy是ES6中提供的新的API,可以用来定义对象各种基本操作的自定义行为,在我们需要对一些对象的行为进行控制时将变得非常有效。

ES6 系列之 defineProperty 与 proxy

我们或多或少都听过数据绑定这个词,数据绑定”的关键在于监听数据的变化,可是对于这样一个对象:var obj = {value: 1},我们该怎么知道 obj 发生了改变呢?ES5 提供了 Object.defineProperty 方法,该方法可以在一个对象上定义一个新属性

Js中Proxy

Proxy 用于修改某些操作的默认行为(基本操作有属性查找,赋值,枚举,函数调用等)。get(target, propKey, receiver):拦截对象属性的读取;set: function(obj, prop, value,receive) : 拦截某个属性的赋值操作

Proxy 的巧用

使用Proxy,你可以将一只猫伪装成一只老虎。下面大约有6个例子,我希望它们能让你相信,Proxy 提供了强大的 Javascript 元编程。尽管它不像其他ES6功能用的普遍,但Proxy有许多用途

使用 Proxy 更好的封装 Storage API

这篇文章提到 Proxy 这种语法可以用来封装 sessionStorage、 localStorage 甚至是 IndexedDB。可以使用 Proxy 代理来使 API 更容易使用。首先介绍一下 Proxy 的基本用法:

Proxy及其优势

通常,当谈到JavaScript语言时,我们讨论的是ES6标准提供的新特性,本文也不例外。 我们将讨论JavaScript代理以及它们的作用,但在我们深入研究之前,我们先来看一下Proxy的定义是什么。

ES6中代理和反射(proxy)

通过调用new proxy()你可以创建一个代理来替代另一个对象(被称为目标),这个代理对目标对象进行了虚拟,因此该代理与该目标对象表面上可以被当做同一个对象来对待。

ES6之Proxy

Proxy用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种『元编程』即对编程语言进行编程。Proxy 是在目标对象之前架设一层『拦截』,外部对对象的访问,都需要经过该层拦截。因此在拦截中对外界的访问进行过滤和改写。

ES6的标准内置对象Proxy

Proxy是ES6规范定义的标准内置对象,可以对目标对象的读取、函数调用等操作进行拦截。一般来说,通过Proxy可以让目标对象“可控”,比如是否能调用对象的某个方法,能否往对象添加属性等等。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!