1. 程式人生 > >JS中的bind(),apply(),call()

JS中的bind(),apply(),call()

語法

fun.bind(thisArg[, arg1[, arg2[, ...]]])

引數
thisArg
當繫結函式被呼叫時,該引數會作為原函式執行時的 this 指向。當使用new 操作符呼叫繫結函式時,該引數無效。
arg1, arg2, …
當繫結函式被呼叫時,這些引數將置於實參之前傳遞給被繫結的方法。

返回值
返回由指定的this值和初始化引數改造的原函式拷貝

描述
bind() 函式會建立一個新函式(稱為繫結函式),新函式與被調函式(繫結函式的目標函式)具有相同的函式體(在 ECMAScript 5 規範中內建的call屬性)。當新函式被呼叫時 this 值繫結到 bind() 的第一個引數,該引數不能被重寫。繫結函式被呼叫時,bind() 也接受預設的引數提供給原函式。一個繫結函式也能使用new操作符建立物件:這種行為就像把原函式當成構造器。提供的 this 值被忽略,同時呼叫時的引數被提供給模擬函式。

理解:
bind()方法主要就是將函式繫結到某個物件,bind()會建立一個函式,函式體內的this物件的值會被繫結到傳入bind()第一個引數的值,例如,f.bind(obj),實際上可以理解為obj.f(),這時,f函式體內的this自然指向的是obj

this.x = 9; 
var module = {
  x: 81,
  getX: function() { return this.x; }
};
 
module.getX(); // 返回 81
 
var retrieveX = module.getX;
retrieveX(); // 返回 9, 在這種情況下,"this"指向全域性作用域
 
// 建立一個新函式,將"this"繫結到module物件
// 新手可能會被全域性的x變數和module裡的屬性x所迷惑
var boundGetX = retrieveX.bind(module);
boundGetX(); // 返回 81

偏函式
bind()的另一個最簡單的用法是使一個函式擁有預設的初始引數。這些引數(如果有的話)作為bind()的第二個引數跟在this(或其他物件)後面,之後它們會被插入到目標函式的引數列表的開始位置,傳遞給繫結函式的引數會跟在它們的後面。

function list() {
  return Array.prototype.slice.call(arguments);
}
 
var list1 = list(1, 2, 3); // [1, 2, 3]
 
// Create a function with a preset leading argument
var leadingThirtysevenList = list.bind(undefined, 37);
 
var list2 = leadingThirtysevenList(); // [37]
var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]

2.apply()和call()
相同點:

  1. 每個函式都包含兩個非繼承而來的方法:call()方法和apply()方法。

    1. 這兩個方法的作用是一樣的。
      都是在特定的作用域中呼叫函式,等於設定函式體內this物件的值,以擴充函式賴以執行的作用域。
      一般來說,this總是指向呼叫某個方法的物件,但是使用call()和apply()方法時,就會改變this的指向。
      不同點:接收引數的方式不同。
      apply()方法 接收兩個引數,一個是函式執行的作用域(this),另一個是引數陣列。
      語法:apply([thisObj [,argArray] ]);,1呼叫一個物件的一個方法,
      2另一個物件替換當前物件。
      說明:如果argArray不是一個有效陣列或不是arguments物件,那麼將導致一個
      TypeError,如果沒有提供argArray和thisObj任何一個引數,那麼Global物件將用作thisObj。

    call()方法: 第一個引數和apply()方法的一樣,但是傳遞給函式的引數必須列舉出來。
    語法:call([thisObject[,arg1 [,arg2 [,…,argn]]]]);,應用某一物件的一個方法,用另一個物件替換當前物件。
    說明: call方法可以用來代替另一個物件呼叫一個方法,call方法可以將一個函式的物件上下文從初始的上下文改變為thisObj指定的新物件,如果沒有提供thisObj引數,那麼Global物件被用於thisObj。


function add(c,d){
        return this.a + this.b + c + d;
    }
    var s = {a:1, b:2};
    console.log(add.call(s,3,4)); // 1+2+3+4 = 10
    console.log(add.apply(s,[5,6])); // 1+2+5+6 = 14 

總結:
call()、apply()可以看做是某個物件的方法,通過呼叫放法的形式來間接的呼叫函式。bind()就是將某個函式繫結到某個物件上。
參考文:
https://blog.csdn.net/huang100qi/article/details/76923086