ES6

ES6学习笔记7:新概念Proxy登场!

Posted by mieruko on 2016-12-11

前言

Proxy是ES6引入的一个新的概念。
它的用途是从语言层面上去操作一个对象
这么说太抽象了,当我没说,看代码吧

Proxy之从一个小🌰说起

假如我们有一个人,叫做Bob Wood。
我们这样形容他:

1
2
3
4
5
var user = {};
user.fname = 'Bob';
user.lname = 'Wood';

full_name = user.fname + " " + user.lname;

想要获取full_name,我们是手动相加了,如果有很多个这样的人,我们懒得写那么多代码,我们就可以写个方法。

1
2
3
4
5
6
7
8
9
var user = {
full_name: function() {
return this.fname + " " + this.lname;
}
};

user.lname = 'Bob';
user.lname = 'Wood';
console.log(user.full_name());

此处我们调用方法来给我们实现属性的合并。

以上是ES5里面的办法。在ES6里面,我们有一个更先进的解决办法:

1
2
3
4
5
6
7
8
var user = new Proxy({},{
get: function(obj, prop) {
return obj.fname + " " + obj.lname;
}
});

user.fname = 'Bob';
user.lname = 'Wood';

现在输出user.full_name,你会发现你没有调用方法,却仍然成功输出了合并后的结果。😄!

Proxy之对小🌰的完善和解释

楼上的代码,我们确实实现了我们想要做到的效果。
不过这时候,如果你输出user.fname,user,lname,甚至输出个根本不存在的user.age,管你输出啥,你会发现他输出的全都是”Bob Wood”。
是不是有毒?????
这就要从Proxy的实质说起了。
首先Proxy它是一个全新的全局构造函数
上面已经表现得很明显了,毕竟它也是new出来的嘛。
这个构造函数创建对象的形式是这样的:

1
var proxy = new Proxy(target, handler);

target,目标对象,handler,句柄。
目标对象的形式就是各种对象,句柄对象(也叫处理器对象)这个名字看上去很厉害,控制所生成代理对象的各种行为,它的实质也是一个对象,不过这个对象必须长这样:

1
2
3
4
5
6
{
set:
xxxx,
get:
xxxx
}

它只能由对象的内部方法组成,句柄方法的完整列表可以在MDN有关代理的页面上找到,一共有14种方法,与ES6中定义的14中内部方法一致。
不过见到比较多的还是覆盖set和get。
句柄的作用,就是你原有对象里面的方法,如果句柄对象里也有,那么句柄对象里面的新方法会覆盖你原有的旧方法
可以把它想象成一个拦截,所有的属性的获取都需要经过这个句柄对象里面的get,其它方法亦然。

因此上面那个例子,所有对象属性的获取都被我们覆写的这一个get给拦截了,因此如果我们想要得到正确的结果,应该这样做:

1
2
3
4
5
6
7
8
var user = new Proxy({},{
get: function(obj, prop) {
switch(prop) {
case 'full_name':
return obj.fname + " " + obj.lname;
}
}
});

如此,就可以输出我们想要的结果了。

结语

ES5里面的get 属性名()和set 属性名(value),这种新的方法形式让我印象很深刻。
ES6更进一步,推出了能够操作所有内部方法的Proxy构造函数,拓展了原有的构造函数,使我们对对象的操作更加灵活了。