ES6新特性:Proxy; 要使用的话, 直接在浏览器中执行即可, nodebabel目前还没有Proxypolyfill;,要使用的话,直接在浏览器中运行就好了, 浏览器的兼容性为:chrome>49或者firefox>18;

  Proxy的基本使用:

  Proxy如其名, 它的作用是在对象和和对象的属性值之间设置一个代理,获取该对象的值或者设置该对象的值, 以及实例化等等多种操作, 都会被拦截住, 经过这一层我们可以统一处理,我们可以认为它就是“代理器” ;

  Proxy是一个构造函数, 使用new Proxy创建代理器, 第一个参数为一个对象, 第二个参数也为一个对象, 返回被包裹后的代理器, 我们使用基本的getset写一个demo:

<script>
var obj = new Proxy({}, {
get : function( target , prop ) {
console.log("我要获取值了");
return target[prop];
},
set : function( target, prop, value) {
console.log("我要设置值了");
target[prop] = value;
}
});
obj.vvvv = ;
obj.vvvv;
</script>

  如果实例化的时候不给第二个参数设置get和set, 相当于没有这个代理器:

var obj = new Proxy({},{});
obj.vvvv = ;
console.log( obj.vvvv );

  如果给一个对象设置两个代理器或者更多的话, 所有的代理器都会生效:

<script>
var obj = new Proxy({}, {
get : function( target , prop ) {
console.log("我要获取值了");
return target[prop];
},
set : function( target, prop, value) {
console.log("我要设置值了");
target[prop] = value;
}
});
obj = new Proxy(obj, {
get : function( target , prop ) {
console.log("我要再获取值了");
return target[prop];
},
set : function( target, prop, value) {
console.log("我要再设置值了");
target[prop] = value;
}
});
obj.vvvv = ;
obj.vvvv;
</script>

  通过代理器, 能够对用户设置的值进行验证,  只有验证通过了才设置到对象上;

let validator = {
set: function(obj, prop, value) {
if (prop === 'age') {
if (!Number.isInteger(value)) {
throw new TypeError('The age is not an integer');
}
if (value > ) {
throw new RangeError('The age seems invalid');
}
};
obj[prop] = value;
}
}; let person = new Proxy({}, validator); person.age = ;
console.log(person.age); //
person.age = 'young'; // 抛异常
person.age = ; // 值太大了,也抛异常

  代理器Proxy有点像Object的geter和seter,  可以认为是geter和seter的扩展:

    <script>
let obj = {
get hehe() {
console.log("获取值哦");
return obj.val;
},
set hehe(value) {
return this.val = value;
}
};
obj.hehe = ;
console.log(obj.val);
console.log(obj.hehe);
</script>

  Proxy的第二个参数

  Proxy的第二个参数为一个对象, 对象的参数为以下的列表, Proxy提供了更多的接口 , 通过不同的参数, 我们可以截获代码的运行并重新处理, 顾名思义, 代理嘛:

  handler.getPrototypeOf()
  handler.setPrototypeOf()
  handler.isExtensible()
  handler.preventExtensions()
  handler.getOwnPropertyDescriptor()
  handler.defineProperty()
  handler.has()
  handler.get()
  handler.set()
  handler.deleteProperty()
  handler.ownKeys()
  handler.apply()
  handler.construct()

  handler.getPrototypeOf(),

  getPrototypeOf方法必须返回一个对象, 否则会报错:

var obj = {};
var proto = {};
var handler = {
getPrototypeOf(target) {
console.log(target === obj); // true
console.log(this === handler); // true
return proto;
}
}; var p = new Proxy(obj, handler);
console.log(Object.getPrototypeOf(p) === proto); // true

  5种触发getPrototypeOf的方法, 包揽了所有了所有获取原型的方法:

var obj = {};
var p = new Proxy(obj, {
getPrototypeOf(target) {
return Array.prototype;
}
});
console.log(
Object.getPrototypeOf(p) === Array.prototype, // true
Reflect.getPrototypeOf(p) === Array.prototype, // true
p.__proto__ === Array.prototype, // true
Array.prototype.isPrototypeOf(p), // true
p instanceof Array // true
);

  handler.setPrototypeOf()

  当对象被设置原型的时候会执行我们设定的代码:

let handler = {
setPrototypeOf : function(target, value) {
console.log("setPrototypeOf");
target.__proto__ = value;
target.hehe = "";
return target;
}
};
let proxy = new Proxy( {}, handler );
proxy.__proto__ = Object.prototype
console.log(proxy);
输出:setPrototypeOf
又输出: {hehe: ""}

  handler.constructor();

  当对象被new的时候会执行handler.constructor方法, 和上面不同的是第一个参数应该为一个函数:

<script>
var p = new Proxy(function() {}, {
construct: function(target, argumentsList, newTarget) {
console.log("called: " + argumentsList.join(", "));
return { value: argumentsList[] * };
}
}); console.log(new p());
//输出:called: 1
//输出:Object {value: 10}
</script>

  Proxy的方法:

    Proxy.revocable()返回一个可以取消的Proxy代理, 当实例化完毕后,在 执行 Proxy实例对象.revoke();   那么这个proxy实例相当于被内存回收, 不存在一样;

var revocable = Proxy.revocable({}, {
get: function(target, name) {
return "[[" + name + "]]";
}
});
var proxy = revocable.proxy;
console.log(proxy.foo); // "[[foo]]"
revocable.revoke();
console.log(proxy.foo); // 抛出异常
proxy.foo = // 抛出异常
delete proxy.foo; // 抛出异常
typeof proxy // "object", 但是它还是一个对象....

  实际应用:

  通过constructapply两个变量, 可以实现一个:继承构造函数的工具函数extend:

function extend(sup,base) {
///获取base方法的constructor
var descriptor = Object.getOwnPropertyDescriptor(
base.prototype,"constructor"
);
//重写base方法的constructor,指向继承超类的对象
base.prototype = Object.create(sup.prototype);
//利用构造器的代理器, 当用户new这个函数的返回对象时候, 会生成一个继承超类和base类的对象
var handler = {
construct: function(target, args) {
var obj = Object.create(base.prototype);
this.apply(target,obj,args);
return obj;
},
apply: function(target, that, args) {
sup.apply(that,args);
base.apply(that,args);
}
};
var proxy = new Proxy(base,handler);
descriptor.value = proxy;
//修复constructor方法
Object.defineProperty(base.prototype, "constructor", descriptor);
return proxy;
} var Person = function(name){
this.name = name;
}; var Boy = extend(Person, function(name, age) {
this.age = age;
}); Boy.prototype.sex = "M"; var Peter = new Boy("Peter", );
console.log(Peter.sex); // "M"
console.log(Peter.name); // "Peter"
console.log(Peter.age); //

  给一个对象绑定一个set,当对象的selected元素发生改变, 那么就改变dom节点的属性:

<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div id="item-1">
item-
</div>
<div id="item-2">
item-
</div> <script>let view = new Proxy({
selected: null
},
{
set: function(obj, prop, newval) {
let oldval = obj[prop]; if (prop === 'selected') {
if (oldval) {
oldval.setAttribute('aria-selected', 'false');
}
if (newval) {
newval.setAttribute('aria-selected', 'true');
}
} // The default behavior to store the value
obj[prop] = newval;
}
}); let i1 = view.selected = document.getElementById('item-1');
console.log(i1.getAttribute('aria-selected')); // 'true' let i2 = view.selected = document.getElementById('item-2');
console.log(i1.getAttribute('aria-selected')); // 'false'
console.log(i2.getAttribute('aria-selected')); // 'true'
</script>
</body>
</html>

  浏览器的DEMO:

let products = new Proxy({
browsers: ['Internet Explorer', 'Netscape']
},
{
get: function(obj, prop) {
// 如果实际的属性为latestBrowser
if (prop === 'latestBrowser') {
return obj.browsers[obj.browsers.length - ];
} // 其他的属性
return obj[prop];
},
set: function(obj, prop, value) {
// 如果实际的属性为latestBrowser
if (prop === 'latestBrowser') {
obj.browsers.push(value);
return;
} // 其他属性的话, 把值转化为数组;
if (typeof value === 'string') {
value = [value];
} // 设置属性
obj[prop] = value;
}
}); console.log(products.browsers); // ['Internet Explorer', 'Netscape']
products.browsers = 'Firefox';
console.log(products.browsers); // 输出: ['Firefox'] products.latestBrowser = 'Chrome';
console.log(products.browsers); // 输出:['Firefox', 'Chrome']
console.log(products.latestBrowser); // 输出:'Chrome'

  参考:

    mdn:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

    阮一峰:http://es6.ruanyifeng.com/#docs/proxy

作者: NONO
出处:http://www.cnblogs.com/diligenceday/

QQ:287101329

微信:18101055830

ES6新特性:Proxy代理器的更多相关文章

  1. ES6新特性概览

    本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代号harmony( ...

  2. 你不知道的JavaScript--Item24 ES6新特性概览

    ES6新特性概览 本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代 ...

  3. ES6新特性概览1

    本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代号harmony( ...

  4. 前端入门21-JavaScript的ES6新特性

    声明 本篇内容全部摘自阮一峰的:ECMAScript 6 入门 阮一峰的这本书,我个人觉得写得挺好的,不管是描述方面,还是例子,都讲得挺通俗易懂,每个新特性基本都还会跟 ES5 旧标准做比较,说明为什 ...

  5. ES6新特性三: Generator(生成器)函数详解

    本文实例讲述了ES6新特性三: Generator(生成器)函数.分享给大家供大家参考,具体如下: 1. 简介 ① 理解:可以把它理解成一个函数的内部状态的遍历器,每调用一次,函数的内部状态发生一次改 ...

  6. ES6新特性之模板字符串

    ES6新特性概览  http://www.cnblogs.com/Wayou/p/es6_new_features.html 深入浅出ES6(四):模板字符串   http://www.infoq.c ...

  7. Atitit js版本es5 es6新特性

    Atitit js版本es5 es6新特性 Es5( es5 其实就是adobe action script的标准化)1 es6新特性1 Es5( es5 其实就是adobe action scrip ...

  8. ES6新特性(函数默认参数,箭头函数)

    ES6新特性之 函数参数的默认值写法 和 箭头函数. 1.函数参数的默认值 ES5中不能直接为函数的参数指定默认值,只能通过以下的变通方式:   从上面的代码可以看出存在一个问题,当传入的参数为0或者 ...

  9. ES6新特性简介

    ES6新特性简介 环境安装 npm install -g babel npm install -g babel-node //提供基于node的REPL环境 //创建 .babelrc 文件 {&qu ...

随机推荐

  1. Activity的onCreate()的PersistableBundle 参数坑。

    Bundle 与 PersistableBundle 区别 仅仅是Activity oncreate()的一个参数与两个参数的区别: @Override public void onCreate(Bu ...

  2. 在嵌入式开发板中运行程序提示-/bin/sh: ./xx: not found的解决办法

    今天拿着我的tiny6410板子,在虚拟机上用 $arm-linux-gcc he.c -o he 编译后放到tiny6410的文件系统中提示 -/bin/sh: ./xx: not found 后来 ...

  3. Eclipse c++代码提示,覆盖下面代码的问题。

    今天在使用Eclipse自动提示时,会覆盖下面行的代码!!! 这个错误几乎不能忍,goolge无果. 手动尝试去掉,全部代码提示,终于找到解法办法,但是原因未知. 如下图:需要去掉 "Par ...

  4. Window 对象

    Window 对象 Window 对象表示浏览器中打开的窗口. 如果文档包含框架(<frame> 或 <iframe> 标签),浏览器会为 HTML 文档创建一个 window ...

  5. 无法安装 DotNetCore.1.0.0-VS2015Tools.Preview2解决方法

    安装 DotNetCore.1.0.0-VS2015Tools.Preview2,已经安装vs2015update3,还是提示检测到 Visual Studio 2015 Update 3没有完全安装 ...

  6. C语言: 创建数组的几种方法

    创建数组有三种方法 1.声明一个数组,声明时用常量表达式指定数组维数,然后可以用数组名访问数组元素 2.声明一个变长数组,声明时用变量表达式指定数组的维数,C99支持 3.声明一个指针,调用mallo ...

  7. 代码整洁--使用CodeMaid自动程序排版

    在项目开发的过程中,如果只是验证命名规则.而没有统一程序排版,项目中很容易就会出现类似下列范例的程序代码产出.这样的产出,虽然能够正常地提供项目功能.并且符合微软的命名规则,但是因为程序排版凌乱的问题 ...

  8. Web服务器之iis,apache,tomcat三者之间的比较

    IIS-Apache-Tomcat的区别 IIS与Tomcat的区别 IIS是微软公司的Web服务器.主要支持ASP语言环境. Tomcat是Java Servlet 2.2和JavaServer P ...

  9. Spring Security笔记:解决CsrfFilter与Rest服务Post方式的矛盾

    基于Spring Security+Spring MVC的web应用,为了防止跨站提交攻击,通常会配置csrf,即: <http ...> ... <csrf /> </ ...

  10. CoreBluetooth——IOS蓝牙4.0使用心得

    原文链接:http://m.blog.csdn.net/article/details?plg_nld=1&id=51014318&plg_auth=1&plg_uin=1&a ...