原文地址:https://segmentfault.com/a/1190000006051586?utm_source=tuicool&utm_medium=referral 本处仅仅个人存档学习,如有侵权,请联系我删除。 Functor
仿函数(Functor)是 C++ 里面一个重要的概念,简而言之就是使用重载了 operator() 运算符的对象模仿函数的行为,带来的收益是仿函数可以携带自身状态,普通的 C++ 函数不是对象,做不到这一点。 js 中的函数本身就是对象,可以携带自身状态,另外还有 curry 化等函数式编程的方法让函数缓存状态,基本上没有仿函数存在的必要。最简单的你可以这样写: function foobar() {
    return foobar.a;
} foobar.a = ;
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(); 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'
最后,这只是个脑洞!每个语言都有自身的规律和方法论。不要真的在项目里这么写,除非你的项目目的就是创造漂亮的语法。  

最新文章

  1. MySQL的基本函数
  2. Linux 内存布局
  3. 初探R语言——R语言笔记
  4. NDK Android* 应用移植方法
  5. c#为了实现自己的线程池功能(一)
  6. Android Monkey压力测试介绍
  7. jstack
  8. 使用ajax提交form表单(转)
  9. typedef如何显示变量类型名
  10. QueryBuilder 前端构造SQL条件的插件使用方法
  11. Linux 出现telnet: 127.0.0.1: Connection refused错误解决办法
  12. 使用python函数持续监控电脑cpu使用率、内存、c盘使用率等
  13. JS 正则表达式从地址中提取省市县
  14. JavaScript -- throw、try 和 catch
  15. Error while executing topic command : Replication factor: 2 larger than available brokers: 0.
  16. 128、View 绘制流程 & 自定义View
  17. Vue项目中跨域的几种方式
  18. c#按照回车换行符分割字符串
  19. Spark优化之gc
  20. Combination Sum leetcode java

热门文章

  1. 关于 html button 点击刷新页面的问题
  2. Vue 上传图片压缩 的问题
  3. 【NOIP2012模拟10.25】剪草
  4. Github Actions教程:运行python代码并Push到远端仓库
  5. postman批量调用接口并发测试
  6. 如何修改 tomcat 端口号?
  7. sh_02_判断年龄改进版
  8. 2019.9.23JAVA动手动脑
  9. Vim 命令、操作、快捷键(收藏大全)
  10. Jupiter Code Review Reference -- Jupiter代码审查工具使用参考