javascript函数式编程 : call 和 apply

买一送一:本系列可让你掌握函数式编程,而且附赠 underscore 技能javascript


平常BB

面对突飞猛进的编程语言都展开了函数式编程大战,灵活古老的javascript怎么不参战?javascript但是自然支持函数基础的元老人物。想要成为一名高逼格的程序员无论你是前端,仍是后台,亦或是全栈,无论你开发webhybrid,怎么能不掌握呢?笔者主要是java从业者,面向对象思想根深蒂固,让咱们以javascript为基石,破然后立,从新学习javascript,进行函数编程,感觉非同通常的编程乐趣。css


要说javascript函数编程 Jquery能够少,可是underscore是必不可少的,无论你是否掌握underscore,后续系列文章可能会大量使用此库。前端

不得不说的第一课

  • call()apply()

掌握call()apply()不是学好函数编程的关键,而是基石,先简单讲下: 其实callapply的存在目的只有一个:改变函数总体内部this的指向,this 这里就不老生常谈了,彻底浪费你们时间,据说不举例子都是耍流氓,我举还不行嘛...java

/**
 * Created by Venda-GM on 2017/10/18.
 */

function Peaple() {}
Peaple.prototype = {
    name:'小明',
    say:function(){
        alert(this.name);
    }
}

var Peaple1 = {
    name:'小强'
}

var peaple = new Peaple();
peaple.say.call(Peaple1); //小强
peaple.say.apply(Peaple1);//小强   
//******************知识点0.0***************
Fn1并无say这个方法,可是fn原型有,那么fn.call...
复制代码

能够看出来: 其中的this被指向了,name并非原来Peaple中的小明git

  • 结论:

不论是call 仍是 apply 都改变了函数的 this 对象程序员

那两个函数总有差距,具体差距呢 --接受参数不同--github

call()方法中的[其他的]参数必须直接传给函数

apply()接收两个参数:一个参数是运行时的做用域,
另外一个是参数数组、或arguments等
复制代码
  • arguments是什么?

call,appply同样,都是每一个function内置的方法,arguments是属性,能够获取到传递到这个方法的所有变量。通常在库中极为常见问底注解①_.toArray就用了。web

  • 了解了以后咱们组合起来作一个例子:

咱们制造一个函数:它 接受一个函数,返回一个函数,并用apply执行返回来的函数。编程

function splat(fun){ 
            return function(array){
                return fun.apply(console,array);
            }
        }
        var addArray = splat(function(x,y){
            this.log(x,y)
            return x+y;
        })
        addArray([1,2]); //3
        
        ```
        
先本身想1分钟,而后我来解析一下发生了啥?

![](https://user-gold-cdn.xitu.io/2017/10/19/3147f656dc04af503316778871056470)

咱们调用`addArray`的时候`addArray`调用了`splat()`函数并向他传递了一个`函数`(咱们简称`解决方案`吧),而他也没干啥好事,最终`splat()`返回的函数说:`“我也解决不了,你的方案不错,就用你的作吧。”` 说完大笔一挥, `fun.apply() `[赞成!] 而且把你提交的`[1,2]`,按照你的解决方案执行了后还给你。

- 而且发现

最终`addArray`内部的`this`对象由`window`转变为了`console`。有人问这有个吊用?下面举例

复制代码
function splat(fun){ 
        return function(array){
            var math_π =[1,4,1,5,9,2,6,5];
            return fun.apply(math_π,array);
        }
    }
    var addArray = splat(function(x,y){
        this.push(x+y)
        console.log(this); //[1,4,1,5,9,2,6,5,3]
        return x+y;
    })
    addArray([1,2]); //3
    
    ```
复制代码

咱们有一个私有属性math_π,并不想设为全局,而且在执行addArray的匿名方法是还想让他对math_π搞事情,那么咱们能够吧指针经过apply指向它,处理一些事情segmentfault

我之前讲的面向对象编程说过,私有的面向对象处理方法是,制造原型链设置get/set方法,在new一个对象,get到便可,面向对象是容易理解,可是是否是有点向java同样繁琐了呢。


刚才例子讲了啥?健忘症又犯了! 讲了咱们实现了一个函数它接受了一个函数,而且返回了一个函数,返回的函数执行了接受的函数,而且改变了做用域。

咱们能够作一个相反的,如有这样一个需求:

我有个方法只接受数组,可是如今有个不可抗力让我只能传字符串,传多少个我也不知道,我该怎么办?

//原始方法
var F = function(array){
            return array.join(' ')
        }
复制代码

想传的数据

1,2,3,4,5,7,7,zzz,www,ddd
复制代码

咱们首先想到arguments,那怎么原封不动F实现需求呢?用call!彻底吻合

//作一个转换器
var ParamsConvertor  =  function(fun) {
    return function(){ //返回一个匿名函数
        fun.call(this,_.toArray(arguments));①
    }
}
复制代码

咱们调用下:

ParamsConvertor(F)(1,2,3,4,5,7,7,'zzz','www','ddd');
复制代码

打印结果:

1 2 3 4 5 7 7 zzz www ddd
复制代码

完美!

这还只是摸到了函数式的一些边缘就已经很兴奋了,正式开始进行编程会怎么样呢?

今天太晚了就先写到这里

ps:①_.toArrayunderscore的一个函数,

toArray_.toArray(list) 
把list(任何能够迭代的对象)转换成一个数组,在转换 arguments 对象时很是有用。

(function(){ return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
=> [2, 3, 4]

复制代码

咱们看到其实他也是运用了arguments对象。


资料:underscore中文文档underscore能够配合使用的还有lodash中文文档 目前先掌握underscore便可。

代码地址

之后博客将首发到这个git库中,并写一个列表,感兴趣能够点下star,点star不迷路,github有归档。


接下来会正式踏足函数式编程,准备好了么,另外设计模式也会尽力持续更新,原本打算一个系列一个系列更新,可是根本按耐不住想写其余的,其实我最近更想写的是java,还想用Electron封装一个elasticsearch客户端、继续维护爬虫框架、想作的事情不少,慢慢来吧。

相关文章
相关标签/搜索