Functor
仿函数(Functor)是 C++ 内里一个主要的观点,简而言之就是运用重载了 operator() 运算符的对象模拟函数的行动,带来的收益是仿函数能够照顾自身状况,一般的 C++ 函数不是对象,做不到这一点。
js 中的函数自身就是对象,能够照顾自身状况,别的另有 curry 化等函数式编程的要领让函数缓存状况,基础上没有仿函数存在的必要。最简朴的你能够如许写:
function foobar() {
return foobar.a;
}
foobar.a = 1;
var b = foobar(); // b=>1
如许,foobar 就照顾了自身状况 a,而且能够在函数体重接见 a。
然则这里有一个题目:函数体中 foobar.a 这一句是应用闭包完成的,个中 foobar 这个援用被写死了,从效果上看 foobar 成了一个单例。假如我想要多个 foobar 实例怎样办呢?
以及,我比较喜好 this 指针,而不是闭包。面临这类状况,我更喜好如许的写法:
// 伪代码
function foobar() {
return this.b;
}
foobar.setB = function (val) {
this.b = val
}
var foo = new foobar;
foo.setB(1);
var b = foo(); // b=>1
js 完成
那末怎样完成呢?我之前写了一篇文章,内里说 js 不容易完成相似的观点。然则当时我没细想,本日试了一下实在更改一下接口,照样能完成相似效果的。
基础的道理就是如许:
function f() {...}
var functor = f.bind(f);
让一个函数 bind 它本身,如许它不就能用 this 接见本身了吗?然则这里另有个题目,bind 的返回效果并非 f 自身而是另一个函数,functor 的持有者在外部接见不到 f。所以这里还要用 js 的新 api defineProperty 处置惩罚一下,使得对 functor 的某些属性接见,转移到 f 上去。
完全的完成以下:
function makeFunctor(fn, props) {
function thisFn() {
return fn.apply(this, Array.prototype.slice.call(arguments));
}
var ret = thisFn.bind(thisFn);
for (var key in props) {
if (!props.hasOwnProperty(key)) {
continue;
}
Object.defineProperty(ret, key, {
configurable : true,
enumerable : true,
get : function () {
return thisFn[key];
},
set : function (value) {
thisFn[key] = value;
}
});
ret[key] = props[key];
}
return ret;
}
经由过程 makeFunctor,我们能够经由过程一个函数 fn 建立很多个 functor,每一个都有自身的状况,互不影响。而且在 fn 中我们能够运用 this 接见自身状况。比方:
function hello () {
alert('Hello, ' + this.name);
}
hello.create = function () {
makeFunctor(hello, {
name : 'Tom'
});
}
var ftHello = hello.create();
var ftHello2 = hello.create();
ftHello(); // Hello, Tom'
ftHello.name = 'Jack';
ftHello(); // Hello, Jack'
ftHello2(); // Hello, Tom'
末了,这只是个脑洞!每一个言语都有自身的规律和要领论。不要真的在项目里这么写,除非你的项目目标就是制造美丽的语法。