2021年11月18日 星期四

JavaScript 的 call、apply、bind

call、apply、bind:將物件變成另一個函式中的this

[測試範例的 物件 和 函式]
物件:var objTest
函式:function test(a, b)

var objTest = {
  x: "xyz"
}

function test(a, b) {
  console.log("this.x=", this.x);
  console.log("a=", a);
  console.log("b=", b);
  console.log("arguments=", Array.from(arguments));
  //console.log("arguments=", [...arguments]);
}
test(1, 2);
//this.x= undefined
//a= 1
//b= 2
//arguments= [1, 2]


[call]
使用call,會直接執行function。
test.call(objTest);
//this.x= xyz
//a= undefined
//b= undefined
//arguments= []

test.call(objTest, 10);
//this.x= xyz
//a= 10
//b= undefined
//arguments= [10]

test.call(objTest, 10, 20);
//this.x= xyz
//a= 10
//b= 20
//arguments= [10, 20]


[apply]
使用apply,會直接執行function。跟call不同,傳入的參數為陣列。
test.apply(objTest);
//this.x= xyz
//a= undefined
//b= undefined
//arguments= []

test.apply(objTest, [10]);
//this.x= xyz
//a= 10
//b= undefined
//arguments= [10]

test.apply(objTest, [10, 20]);
//this.x= xyz
//a= 10
//b= 20
//arguments= [10, 20]


[bind]
使用bind,會回傳綁定後的function,綁定時可選擇是否綁定參數值,沒綁定的參數值,可使用時再傳入。
//只綁定this物件
var ff = test.bind(objTest);
ff();
//this.x= xyz
//a= undefined
//b= undefined
//arguments= []

ff(10);
//this.x= xyz
//a= 10
//b= undefined
//arguments= [10]

ff(10, 20);
//this.x= xyz
//a= 10
//b= 20
//arguments= [10, 20]
//綁定了this物件,和第一個參數a=10,則使用時,參數a不須也無法再傳值,a固定為10
var ff = test.bind(objTest, 10);
ff();
//this.x= xyz
//a= 10
//b= undefined
//arguments= [10]

ff(20); //已綁定了第一個參數a=10,所以剩下的參數只剩一個,此處傳的是b=20
//this.x= xyz
//a= 10
//b= 20
//arguments= [10, 20]

ff(50, 60); //多傳的參數60,不會用到
//this.x= xyz
//a= 10
//b= 50
//arguments= [10, 50, 60]
//綁定了this物件,和第一個參數a=10,第二個參數b=10,則使用時,參數a、參數b不須也無法再傳值,a固定為10,b固定為20
var ff = test.bind(objTest, 10, 20);
ff();
//this.x= xyz
//a= 10
//b= 20
//arguments= [10, 20]

ff(91, 92);
//this.x= xyz
//a= 10
//b= 20
//arguments= (4) [10, 20, 91, 92]



[應用]
  • 處理偽陣列(類似陣列,但不是陣列的資料,當成陣列處理)
    function aa() {
      //arguments 不是陣列,不能使用 slice、push...
      //arguments.slice(1)
      //Uncaught TypeError: arguments.slice is not a function
      console.log([].slice.call(arguments, 1));
    }
    
    aa("a", "b", "c", "d");
    //['b', 'c', 'd']
  • 取陣列最大最小值
    var arr = [5, 2, 8, -9];
    //原本要處理成 Math.max(5, 2, 8, -9),剛好可用 apply 用陣列傳遞參數的特性。
    //現在也可以使用 ...展開運算子(Spread syntax),直接寫成 Math.max(...arr)。
    //Math.max.apply(null, arr),第一個物件參數沒用到,隨意傳個東西,
    //第一個物件參數傳null、undefined,在非嚴格模式(non-strict),會被置換成global object(在瀏覽器即為window物件)
    console.log(Math.max.apply(null, arr));
    //8



參考:

沒有留言:

張貼留言