js中的bind call apply

知道了js中的this的具體用法之后譬巫,感覺還是總結(jié)一下bind call apply的使用吧,算是一個知識整合的過程嘿嘿~~


這三個堪稱js中的神器,可以改變this的指向吁断,實現(xiàn)函數(shù)的“借用”僻他。畢竟js還是挺悶騷的萧朝,動不動就出現(xiàn)函數(shù)執(zhí)行環(huán)境的改變,所以我們需要強行把this的指向重新掰過來鹿蜀,這個時候就需要用到這個神器了箕慧。

  • bind 的使用;
  • call和apply的使用茴恰;
  • apply的一點使用小技巧(參數(shù)為數(shù)組颠焦,好好利用)

js中的this很重要(可以先看一下這一篇):http://www.reibang.com/p/adaf787a0d4d#

bind

1 bind 可以設置函數(shù)調(diào)用的this指向
?var user = {
    data        :[
        {name:"T. Woods", age:37},
        {name:"P. Mickelson", age:43}
    ],
    clickHandler:function (event) {
        var randomNum = ((Math.random () * 2 | 0) + 1) - 1; // random number between 0 and 1?
?
        //隨機生成一個數(shù),來調(diào)用data
        $ ("input").val (this.data[randomNum].name + " " + this.data[randomNum].age);
    }
?
}

?// 給按鈕添加點擊事件
$ ("button").click (user.clickHandler);

如果看過前面的this的文章往枣,應該知道這樣調(diào)用伐庭,其實this不再指向user粉渠,而是指向 $ ("button").。所以可以借用bind更改圾另;

$ ("button").click (user.clickHandler);

更改如下(此時this就重新指向了user了)

$ ("button").click (user.clickHandler.bind (user));

2 bind可以借用函數(shù)

   var user = {
                // local data variable?
                data    :[
                    {name:"T. Woods", age:37},
                    {name:"P. Mickelson", age:43}
                ],
                showData:function (event) {
                    var randomNum = ((Math.random () * 2 | 0) + 1) - 1; // random number between 0 and 1?
?
                    console.log (this.data[randomNum].name + " " + this.data[randomNum].age);
                }
?
            }
            var cars = {
                data:[
                    {name:"Honda Accord", age:14},
                    {name:"Tesla Model S", age:2}
                ]
?
            }
?
            // 我們可以借用我們這個例子中user的方法
            //現(xiàn)在我們可以使用bind來將this的指向更改為cars霸株,函數(shù)將會調(diào)用里面的方法
            cars.showData = user.showData.bind (cars);
            cars.showData (); // Honda Accord 14?

2 call 和 apply的使用

  • 相同點:
    call和apply都可以修改this的指向,第一個參數(shù)是要引用的對象集乔,第二個參數(shù)是要傳進函數(shù)的變量

  • 不同點:
    call的變量參數(shù)是一個個參數(shù)去件;
    apply的變量參數(shù)是數(shù)組;

call和bind 都可以設置 this

// 設置一個全局變量
        var avgScore = "global avgScore";
?
        //全局函數(shù)
        function avg (arrayOfScores) {
            // 添加所有的分數(shù)并返回總數(shù)
            var sumOfScores = arrayOfScores.reduce (function (prev, cur, index, array) {
                return prev + cur;
            });
?
            // 這里的this指向的是全局global除非我們用call將其進行更改
            this.avgScore = sumOfScores / arrayOfScores.length;
        }
?
        var gameController = {
            scores  :[20, 34, 55, 46, 77],
            avgScore:null?
        }
?
        // 這樣執(zhí)行的話扰路,this就是指向全局的window
        avg (gameController.scores);
        // 以下的輸出可以證明this是指向全局的this的尤溜,后面的還是輸出null
        console.log (window.avgScore); // 46.4?
        console.log (gameController.avgScore); // null?
?
        // reset the global avgScore?
        avgScore = "global avgScore";
?
        //設置this值,此時this就綁定給了gameController
        // 使用call方法
        avg.call (gameController, gameController.scores);
?
        console.log (window.avgScore); //global avgScore?
        console.log (gameController.avgScore); // 46.4?

還有一點汗唱,就是可以用這兩個方法來調(diào)用 Array的一些自帶的方法靴跛,我們都知道js里有一些神奇的變量,就是 類數(shù)組.格式上很像數(shù)組渡嚣,但是沒有數(shù)組的一些基本方法梢睛。slice 等方法。
這個時候识椰,我們可以通過 call apply 的方法绝葡,來借用Array.prototype的方法。

看個栗子吧腹鹉。

類數(shù)組:

//這是類數(shù)組的定義方法藏畅,需要給定一個lenth的屬性來表示該數(shù)組的長度才有效。
var anArrayLikeObj = {0:"Martin", 1:78, 2:67, 3:["Letta", "Marieta", "Pauline"], length:4 };

現(xiàn)在這個變量是沒有數(shù)組中的原生方法的功咒,那么怎么去調(diào)用呢愉阎?這個時候就可以用call和bind了

Array.prototype是數(shù)組的原型,數(shù)組的基本方法都是從原型繼承而來力奋。
 var newArray = Array.prototype.slice.call (anArrayLikeObj, 0);
?
                console.log (newArray); // ["Martin", 78, 67, Array[3]]?
?
                // 可以使用數(shù)組中的indexOf方法榜旦,來查找對應的元素
                console.log (Array.prototype.indexOf.call (anArrayLikeObj, "Martin") === -1 ? false : true); // true?
?
                // 不要使用call試一下,發(fā)現(xiàn)報錯了景殷,因為沒有該方法
                console.log (anArrayLikeObj.indexOf ("Martin") === -1 ? false : true); // Error: Object has no method 'indexOf'?
?
                // 反轉(zhuǎn)
                console.log (Array.prototype.reverse.call (anArrayLikeObj));
                // {0: Array[3], 1: 67, 2: 78, 3: "Martin", length: 4}?
?
                // 太棒了溅呢,我們還可以使用pop方法
                console.log (Array.prototype.pop.call (anArrayLikeObj));
                console.log (anArrayLikeObj); // {0: Array[3], 1: 67, 2: 78, length: 3}?
?
                // 再試一下push
                console.log (Array.prototype.push.call (anArrayLikeObj, "Jackie"));
                console.log (anArrayLikeObj); // {0: Array[3], 1: 67, 2: 78, 3: "Jackie", length: 4}?
           

那再來一個,我們都知道猿挚,傳入function的變量是一個類數(shù)組咐旧,叫
arguments .我們可以用相關的函數(shù)對傳入的參數(shù)進行操作。

                // 我們沒有設置參數(shù)的數(shù)目绩蜻,可以對參數(shù)進行操作铣墨。
                function doSomething () {
                    var args = Array.prototype.slice.call (arguments);
                    console.log (args);
                }

              doSomething ("Water", "Salt", "Glue"); // ["Water", "Salt", "Glue"]?
            
靈活應用apply的參數(shù)為數(shù)組的屬性,因為apply的參數(shù)是數(shù)組办绝,所以特別適用于可變函數(shù)的應用伊约。就是函數(shù)的參數(shù)不固定的情況下词顾;

當我們傳入一個數(shù)組的時候,其實函數(shù)會像這樣去執(zhí)行函數(shù),將數(shù)組中的一個個變量傳入碱妆;

createAccount (arrayOfItems[0], arrayOfItems[1], arrayOfItems[2], arrayOfItems[3]);


Math.max() 就是一個可變參數(shù)函數(shù)肉盹;

console.log (Math.max (23, 11, 34, 56)); // 56

但是我們不能把數(shù)組傳給Math.max() ;

var allNumbers = [23, 11, 34, 56];
//我們不能把數(shù)組傳給該方法?
console.log (Math.max (allNumbers)); // NaN

可以這么做疹尾;

var allNumbers = [23, 11, 34, 56];
//使用apply方法上忍,我們可以傳遞數(shù)組給該方法
console.log (Math.max.apply (null, allNumbers)); // 56

因為不需要更改this的指向,所以可以把第一個參數(shù)設置成null纳本。

####最后的最后窍蓝,我們再來理一理;先看一下這個例子繁成;
看看apply和call的真正區(qū)別吓笙;

//下面兩種方法其實就是等同的;
var s1 = ["lili","小明"巾腕,"小紅","彤彤"]
function welcomeStudents () {
console.log(arguments)
}
welcomeStudents.call(null, "lili","小明"面睛,"小紅","彤彤");
welcomeStudents.apply(null, s1);

那我們可以有什么應用場景呢?apply的參數(shù)是數(shù)組尊搬,其實可以做很多的事情叁鉴,我們不用像使用call那樣,一個一個的傳入?yún)?shù)佛寿,只需要將參數(shù)存放在一個數(shù)組里就可以。

如果現(xiàn)在讓你定義一個welcome的函數(shù)冀泻,該函數(shù)的作用是對輸入的名字,做一定的操作弹渔;
>像輸入 var s1 = ["lili","小明","小紅","彤彤"]捞附,可以相對應的輸出.
       ```歡迎 lili,小明巾乳,小紅和彤彤。```

你會怎么做呢鸟召?

var students = ["lili","小明"氨鹏,"小紅","彤彤"];
?
// 我們沒有設置參數(shù),因為參數(shù)的長度沒有被限制
function welcomeStudents () {
var args = Array.prototype.slice.call (arguments);
?
var lastItem = args.pop ();
console.log ("歡迎" + args.join (", ") + ", 和 " + lastItem + ".");
}
?
welcomeStudents.apply (null, students);
// 歡迎 lili,小明仆抵,小紅和彤彤跟继。
//如果你一定要用call方法种冬,那你就得這么做;
welcomeStudents.call (null, "lili","小明"舔糖,"小紅","彤彤");


最后的最后,細心的你也應該會發(fā)現(xiàn)金吗,這三個還有一點點區(qū)別就是,bind不是立即執(zhí)行的摇庙,call和apply的使用則是立即執(zhí)行的;

可以回去看看前面我提到的bind 的那個例子卫袒,綁定按鈕的點擊事件的時候,使用bind來綁定user宝穗,因為事件是在點擊之后才觸發(fā),所以這個時候用bind會比較好讽营。使用call和apply的話,則在還沒有點擊的時候就執(zhí)行了橱鹏。

$ ("button").click (user.clickHandler.bind (user));
//平時我們定義的時候堪藐,也是只寫函數(shù)名的,$ ("button").click (函數(shù)名);而不是$ ("button").click (函數(shù)名());

總結(jié)一下吧:

- call apply 立即執(zhí)行函數(shù)礁竞,apply的參數(shù)是數(shù)組,call的參數(shù)是參數(shù)變量
- bind 返回函數(shù)名模捂,非立即執(zhí)行

showData = user.showData.bind (cars);
cars.showData ();
等效于:
user.showData.call (cars);
user.showData.apply(cars);

>啊,原來整理知識這么不容易综看;休息會了;今天在咖啡廳呆了一天了红碑,五一還是不想出去呀,
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末羡鸥,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子忠寻,更是在濱河造成了極大的恐慌,老刑警劉巖衷旅,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祭饭,死亡現(xiàn)場離奇詭異,居然都是意外死亡倡蝙,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門寺鸥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來猪钮,“玉大人,你說我怎么就攤上這事胆建。” “怎么了扑馁?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵凉驻,是天一觀的道長。 經(jīng)常有香客問我涝登,道長,這世上最難降的妖魔是什么胀滚? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮顷编,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘勾效。我一直安慰自己叛甫,他們只是感情好,可當我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布其监。 她就那樣靜靜地躺著,像睡著了一般毁菱。 火紅的嫁衣襯著肌膚如雪锌历。 梳的紋絲不亂的頭發(fā)上贮庞,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天窗慎,我揣著相機與錄音,去河邊找鬼遮斥。 笑死扇丛,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的帆精。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼隘蝎,長吁一口氣:“原來是場噩夢啊……” “哼昆庇!你這毒婦竟也來了末贾?” 一聲冷哼從身側(cè)響起整吆,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拴测,沒想到半個月后府蛇,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年妆距,在試婚紗的時候發(fā)現(xiàn)自己被綠了函匕。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡中剩,死狀恐怖抒寂,靈堂內(nèi)的尸體忽然破棺而出结啼,到底是詐尸還是另有隱情屈芜,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布糕珊,位于F島的核電站毅糟,受9級特大地震影響红选,放射性物質(zhì)發(fā)生泄漏姆另。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一蝶防、第九天 我趴在偏房一處隱蔽的房頂上張望明吩。 院中可真熱鬧间学,春花似錦印荔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽善涨。三九已至,卻和暖如春蟹漓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背牧牢。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工姿锭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留伯铣,地道東北人。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓腔寡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親忿磅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容