因為在工作中看到bind,搞了很久之後才發現自己根本把bind和apply、call搞混了,決定先把這個部分給搞清楚。
前言
當我們在建立一個物件或函式(特別的物件)時,除了我們給他的東西以外,JavaScript還會同時給它三個方法:bind、call、apply。
Bind
funcToCopy.bind(ObjToBind,[參數1, 參數2]):回傳一個函數,該函數的this指向您指定的物件,如有傳入參數,則該參數將會被固定。
首先介紹 bind(),我們都知道JavaScript有this這個神奇又容易出錯東西,當我們在物件外呼叫this時,this會指向全域變數,例如:瀏覽器就是指向window
,但是如果我們在物件內呼叫this,this則指向這個物件,大家先看一下以下範例:
// 建立一個person物件
let person = {
firstName: "Johlmike",
lastName: "Lin",
getFullName: function(){
return this.firstName + " " + this.lastName;
}
};
// 建立一個otherPerson物件
let otherPerson = {
firstName: "Angelica",
lastName: "Chih"
};
console.log(person.getFullName()); // "Johlmike Lin"
console.log(otherPerson.getFullName()); // Error!
我想大家都知道這個結果,因為在otherPerson裡面並沒有getFullName這個函數,所以我們要用bind來幫忙一下。
// 建立一個person物件
let person = {
firstName: "Johlmike",
lastName: "Lin",
getFullName: function(){
return this.firstName + " " + this.lastName;
}
};
// 建立一個otherPerson物件
let otherPerson = {
firstName: "Angelica",
lastName: "Chih"
};
// 複製 getFullName 函數到 copyGetFullName ,並將 this 綁到 otherPerson
let copyGetFullName = person.getFullName.bind(otherPerson);
console.log(person.getFullName()); // "Johlmike Lin"
console.log(copyGetFullName()); // "Angelica Chih"
Call 和 Apply
funcToCall.call(objToBind, arg_1, arg_2):執行該函數,並且該函數的this指向您指定的物件,參數也使用您傳入的參數。
funcToApply.apply(objToBind, [arg_1, arg2]):基本上與call相同,但傳入參數的部分是接受一整個含有參數的陣列,而不是一個一個的參數。
call和apply基本上是一樣的東西,唯獨傳入的東西不一樣而已,和Bind不同的地方則是,這兩個函數會直接執行,並回傳這個函數該回傳的東西,來看以下範例應該很快就能清楚了:
// 建立一個person物件
let person = {
firstName: "Johlmike",
lastName: "Lin",
getFullName: function(){
return this.firstName + " " + this.lastName;
}
};
// 建立一個otherPerson物件
let otherPerson = {
firstName: "Angelica",
lastName: "Chih"
};
// 立刻執行getFullName函數,this指向otherPerson,並回傳結果至otherPersonFullName
// call可改成apply
let otherPersonFullName = person.getFullName.call(otherPerson);
console.log(person.getFullName()); // "Johlmike Lin"
console.log(otherPersonFullName); // "Angelica Chih"
示範傳入參數:
// 建立一個person物件
let person = {
firstName: "Johlmike",
lastName: "Lin"
};
// 建立一個otherPerson物件
let otherPerson = {
firstName: "Angelica",
lastName: "Chih"
};
// 定義一個sayHello函數,接受一個招呼詞參數
function sayHello(helloWord) {
console.log(this.firstName + " " + this.lastName + ", " + helloWord);
}
sayHello.call(person, "nice to meet you!");// "Johlmike Lin, nice to meet you!"
sayHello.apply(otherPerson, ["good day!"]);// "Angelica Chih, good day!"
Function Borrowing
其實就是跟其他物件借函數用的意思,示範一下大家就懂了,非常簡單好懂。
// 建立一個person物件
let person = {
firstName: "Johlmike",
lastName: "Lin",
getFullName: function(){
return this.firstName + " " + this.lastName;
}
};
// 建立一個otherPerson物件
let otherPerson = {
firstName: "Angelica",
lastName: "Chih"
};
console.log(person.getFullName()); // "Johlmike Lin"
// person有getFullName,otherPerson沒有
// 但是otherPerson想用getFullName
// 只好借一下了!
console.log(person.getFullName.call(otherPerson)); // "Angelica Chih"
Function Currying
老實說我自己也不太清楚currying的意思,所以可能會有點出入,Function Currying可以把一個函數所要傳入的參數給簡化,簡單來說,就是把函數的某個或某些參數值給固定住的意思。
還記得bind嗎?好像有個功能沒提到,bind除了可以複製一份自己、綁定this並回傳以外,還可以讓這個複製的函數的參數固定,就像這樣:
// 這個函數會把參數相乘
function mutiply(num1, num2){
console.log(num1 * num2);
}
// 複製一份,這次綁定的東西不管他,固定num1為5
var otherFunc = mutiply.bind(this, 5);
// 執行時會直接跳過第一個被固定的參數,直接傳給num2
otherFunc(10); // 5 * 10 = 50
otherFunc(20); // 5 * 20 = 100
otherFunc(100, 5); // 5 * 100 = 500
// 再複製一份,這次兩個參數都固定,num1為5,num2為20
var otherFunc2 = mutiply.bind(this, 5, 20);
// 不管輸入什麼都是 5 * 20 = 100
otherFunc2(10, 10); // 5 * 20 = 100
otherFunc2(20, 40); // 5 * 20 = 100
otherFunc2(100, 7); // 5 * 20 = 100
發佈留言