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

时间: 2024-11-29 05:28:19

js Functor Copy的相关文章

Angular.js 中 copy 赋值与 = 赋值 区别

转自st.gg Angular.js 中 copy 赋值与 = 赋值 区别 为什么用 $scope.user = $scope.master; $scope.master 会跟着 $scope.user 改变?angular.copy 和 = 号赋值有什么区别呢?新手还没有搞懂,请教各位了. <!DOCTYPE html> <html> <script src= "http://apps.bdimg.com/libs/angular.js/1.3.9/angular

js实现copy

在js中实现copy.看似很简单的功能.实际上却有点复杂.因为只有能select的元素或者contentEditable的元素才支持document.execCommand('copy'),所以经过百度之后发现了 range这么个属性 function copy(copyEle) { if (copyEle.nodeName.toLowerCase() === "input") { copyEle.select(); document.execCommand('copy'); } el

Meteor node.js 复制(copy)文件的方法

以下三种方法中请注意加: var exec = Npm.require('child_process').exec; var fs =Npm.require('fs'); 1.  原文件在private目录下,用Meteor 的Assets读取内容,使用node.js的fs.writeFile()写入,这种方法只能适用文本文件 var copyFile=function(){ //检测目标文件是否存在 fs.open( FILE_STORE_AB_PATH+"/aapt",'r',fu

js 对象 copy 对象

function clone(myObj) { if (typeof (myObj) != 'object') return myObj; if (myObj == null) return myObj; var myNewObj = new Object(); for (var i in myObj) myNewObj[i] = clone(myObj[i]); return myNewObj; } var test=clone(model);

JS 点击复制Copy

1.实现点击按钮,复制文本框中的的内容 1 <script type="text/javascript"> 2 function copyUrl2() 3 { 4 var Url2=document.getElementById("biao1"); 5 Url2.select(); // 选择对象 6 document.execCommand("Copy"); // 执行浏览器复制命令 7 alert("已复制好,可贴粘.&

js实现点击copy,可兼容

在实现功能时写的一个小demo,可以实现点击复制内容(任何你需要copy的文字内容data). 经测试,可兼容 chrome, edge, firefox, ie, opera, safari,至于版本的话肯定是有限制的,你可以尝试一下版本的底线. 下面就是demo,你可以使用在任何地方. 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>

js copy

Javascript 实现复制(Copy)动作方法大全 投稿:hebedich 字体:[增加 减小] 类型:转载 时间:2014-06-20我要评论 现在浏览器种类也越来越多,诸如 IE.Firefox.Chrome.Safari等等,因此现在要实现一个js复制内容到剪贴板的小功能就不是一件那么容易的事了. 一.实现点击按钮,复制文本框中的的内容 ? 1 2 3 4 5 6 7 8 9 10 11 <script type="text/javascript"> functi

常用js特效

事件源对象  event.srcElement.tagName event.srcElement.type 捕获释放  event.srcElement.setCapture();  event.srcElement.releaseCapture(); 事件按键  event.keyCode event.shiftKey event.altKey event.ctrlKey 事件返回值  event.returnValue 鼠标位置 event.x event.y 窗体活动元素  documen

JS代码大全 (都是网上看到 自己整理的)

原文 JS代码大全 (都是网上看到 自己整理的) 事件源对象 event.srcElement.tagName  event.srcElement.type 捕获释放 event.srcElement.setCapture();   event.srcElement.releaseCapture(); 事件按键 event.keyCode  event.shiftKey  event.altKey  event.ctrlKey 事件返回值 event.returnValue 鼠标位置 event