iT邦幫忙

2023 iThome 鐵人賽

DAY 25
0
自我挑戰組

複習 JavaScript 核心概念系列 第 25

[Day 25] 函式原型中的 apply()、bind()、call()

  • 分享至 

  • xImage
  •  

昨天說到透過 this 關鍵字會在不同情境中取到不同的值,雖然會如何取值都是根據規範而來的,但實際上我們能手動改變 this 的指向,那就是透過函式原型的 apply()bind()call() 方法。透過這三者將使 this 不再根據原本的規則動態取值,而是永遠會拿到開發者所指定的物件。


Function.prototype.apply()

語法

fun.apply(thisArg, [argsArray])

參數

thisArg:要指定的 this 的值。
(非嚴格模式下,null 及 undefined 將會被全域物件取代,而原始型別將被包裝成物件)

argsArray:一個 array-like 物件,這裡就是放原本函式需要的參數。

範例

function greet(a0, a1) {
  console.log(this.favorite, a0, a1);
}

const myObj = {
  favorite: 'Apple'
}

// 正常呼叫函式會輸出「undefined 'Banana' 'Egg'」,其中 this 根據規則指向全域物件
greet('Banana', 'Egg'); 

// 透過 apply 呼叫函式會輸出「'Apple' 'Banana' 'Egg'」,其中 this 的值被指定為 myObj
greet.apply(myObj, ['Banana', 'Egg']);

Function.prototype.call()

語法

fun.apply(thisArg, arg1, arg2, ...)

參數

thisArg:要指定的 this 的值。
(非嚴格模式下,null 及 undefined 將會被全域物件取代,而原始型別將被包裝成物件)

arg1, arg2, ...:原本函式需要的參數。
(跟 apply 用法很像,只是沒有透過類陣列的形式包起來)

範例

function greet(a0, a1) {
  console.log(this.favorite, a0, a1);
}

const myObj = {
  favorite: 'Apple'
}

// 正常呼叫函式會輸出「undefined 'Banana' 'Egg'」,其中 this 根據規則指向全域物件
greet('Banana', 'Egg'); 

// 透過 call 呼叫函式會輸出「'Apple' 'Banana' 'Egg'」,其中 this 的值被指定為 myObj
greet.call(myObj, 'Banana', 'Egg');

Function.prototype.bind()

bind() 方法與前兩者不同,它會回傳一個 this 被綁定的新函式。該新函式被呼叫時, this 的值會是 bind 指定的參數,其他地方與原函式相同。

語法

fun.bind(thisArg)

範例

function greet(a0, a1) {
  console.log(this.favorite, a0, a1);
}

const myObj = {
  favorite: 'Apple'
}

// 正常呼叫函式會輸出「undefined 'Banana' 'Egg'」,其中 this 根據規則指向全域物件
greet('Banana', 'Egg'); 


// newGreet 是透過 bind 建立的新函式,它的 this 的值被指定為 myObj
const newGreet = greet.bind(myObj);
newGreet('Banana', 'Egg'); // 輸出「'Apple' 'Banana' 'Egg'」

這些函式原型的方法可以讓我們更加彈性的指定 this 的值,其中 applycall 用法接近,而 bind 則是用再建立一個綁定 this 的函式。不過雖然它們很方便,不過在非不得已的情況下還是別太常使用比較好,畢竟這已經脫離了原本 this 的規則。尤其是透過 bind() 建立的新函式,呼叫方式跟原函式完全相同,容易發生在呼叫函式時沒注意到它的 this 的值已經被綁死,從而導致不可預期的錯誤。這是要多加注意的!


上一篇
[Day 24] this
下一篇
[Day 26] Promise 與 Async Function(Async / Await)
系列文
複習 JavaScript 核心概念30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言