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客戶端、繼續維護爬蟲框架、想作的事情不少,慢慢來吧。

相關文章
相關標籤/搜索