• js Functor Copy


    原文地址: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 = 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'
    最后,这只是个脑洞!每个语言都有自身的规律和方法论。不要真的在项目里这么写,除非你的项目目的就是创造漂亮的语法。

  • 相关阅读:
    JavaScript学习笔记(六)——Map、Set与iterable
    JavaScript学习笔记(五)——条件判断与循环
    JavaScript学习笔记(四)——对象
    JavaScript学习笔记(三)——数组
    抽象代数 第三章 群
    进栈序列为(1,2,3..,n)有多少种出栈顺序
    Win10 快捷键
    主项定理Master Method
    算法导论笔记 第三十章 多项式与快速傅里叶变化
    算法导论笔记 第二十九章 线性规划
  • 原文地址:https://www.cnblogs.com/shidengyun/p/5703193.html
Copyright © 2020-2023  润新知