JavaScript语言教程
使用Javascript ES6的Proxy实现元编程
使用ecmascript6 中的Proxy可以实现元编程,以以前不可能的方式定义JS对象,下面是Mozilla的一个小案例:
var proxy;
var handler = {
has: function (name) {
return name == 'foo';
},
get: function (rcvr, name) {
if (name != 'foo')
return undefined;
print(proxy !== rcvr);
return "bye";
},
};
proxy = Proxy.create(handler);
var c = Object.create(proxy);
print(c.foo); // prints: 'true' (from "proxy !== rcvr") and 'bye' (from "c.foo").
// In this example, the get trap rcvr argument is the c object while proxy is its prototype
如果你熟悉Java,这非常类似Java中的动态代理模式,Spring的AOP/IOC框架都是基于动态代理实现的在这个案例我们得到的c这个对象其实是原来真正c原型对象的代理,并不不是真正的c对象,是一个代理人,原型和代理人之间关系类似明星和经纪人之间关系,具体可参考代理模式。
Pipe实现
我们可以使用Proxy实现很酷的Pipe管道化:
var pipe = (function () {
var pipe;
return function (value) {
pipe = [];
return Object.create(Proxy.create({
get: function (pipeObject, fnName) {
if (fnName == "get")
return pipe.reduce(function (val, fn) { return fn(val); }, value);
pipe.push(window[fnName]);
return pipeObject;
}
}));
}
}());
var double = function (n) { return n*2 },
pow = function (n) { return n*n },
reverseInt = function (n) { return n.toString().split('').reverse().join('')|0 };
var pipedExample = pipe(3) . double . pow . reverseInt . get
console.log(pipedExample); //63
注意倒数第二行pipedExample的赋值方式,是不是很像一个个水管衔接在一起呢?
查询代理
使用代理Proxy我们能创建一个查询代理,如果过滤语法,可以过滤从仓储查询的JSON:
var ChristmasList = Repository([
{
name: "Daniel",
age: 12,
wants: "a dog",
},
{
name: "Julia",
age: 8,
wants: "a bottle of rum"
},
{
name: "Vitaly",
age: Infinity,
wants: "a dog"
},
{
name: "Ina",
age: 20,
wants: "Vitaly"
}
]);
ChristmasList.wants['a dog'].get; // [ {age: 12, name: "Daniel",wants: "a dog"}, {age: Infinity, name: "Vitaly", wants: "a dog"} ]
ChristmasList.age['<']['12'].get; // {name: "Julia", age: 8, wants: "a bottle of rum"}
ChristmasList.wants['a dog'].age[">"]["12"].get; // {name: "Vitaly", age: Infinity, wants: "a dog"};
ChristmasList.wants[
ChristmasList.wants['a dog'].age[">"]["12"].get.name
].get // {name: "Ina", age: 20, wants: "Vitaly"}
更多Cool的Proxy应用见:Github repository.