前言:
call
、apply
、bind
這三個方法可以改變 Function 內的動態 this
。
參考資料:
JavaScript 核心篇
[JavaScript] 函數原型最實用的 3 個方法 — call、apply、bind
JavaScript - call,apply,bind
[筆記] 了解function borrowing和function currying ─ bind(), call(), apply() 的應用
使用時機:
都是用再明確指定 this
的時候。
Call
1 2 3 4 5 6 7 8 9 10 11
| let family ={ name:"小明", age:25 }
function fn(para1,para2){ console.log(this,para1,para2); }
fn(1,2); fn.call(family,3,4);
|
我們可以看到透過 call
方法,我們將函式內的 this
取代為外部傳入的 family
物件
Apply
與 call
差異只在於 apply
必須傳入陣列,如過不是傳入陣列資料則會顯示下面錯誤訊息
1 2 3 4 5 6 7 8 9 10 11
| let family ={ name:"小明", age:25 }
function fn(para1,para2){ console.log(this,para1,para2); }
fn.apply(family,[5,6]);
|
Bind
與上面兩者差異在於 Bind 是回傳一個回呼函式
1 2 3 4 5 6
| function fn(para1,para2){ console.log(this,para1,para2); }
let temp = fn.bind(family,7,8); temp();
|
差異
- apply 用在當函式傳入數量不固定,且是陣列
- bind 會回傳一個包裹函式,當我們執行這個函式時,同時也會將帶入 bind 的 arguments 一起帶進 Function 中。
補充
在非嚴格模式下,null
、undefined
將會被置換成全域變數,反之則不會
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| "use strict";
function fn(para1,para2){ console.log(this,para1,para2); }
fn.call(null,3,4); fn.apply(undefined,[5,6]); let temp = fn.bind(null,7,8); temp();
function fn(para1,para2){ console.log(this,para1,para2); }
fn.call(null,3,4); fn.apply(undefined,[5,6]); let temp = fn.bind(null,7,8); temp();
|
實際應用場景
- 我們在取 callBack Function 的 this 時候,都會拿不到正確的 this。
1 2 3 4 5 6 7 8 9 10 11 12 13
| var vm = "全域";
var family = { vm: "小明", callName: function () { console.log('1',this); setTimeout(function () { console.log(this,this.vm); }, 1000); }, }; family.callName();
|
- 過往作法,是在外層直接指定
const self = this
1 2 3 4 5 6 7 8 9 10 11 12 13
| var vm = "全域"; var family = { vm: "小明", callName: function () { const self = this; console.log('1',self ); setTimeout(function () { console.log(self,self.vm); }, 1000); }, }; family.callName();
|
- 直接使用 bind 綁定
1 2 3 4 5 6 7 8 9 10 11 12
| var vm = "全域";
var family = { vm: "小明", callName: function () { console.log('1',this); setTimeout(function () { console.log(this,this.vm); }.bind(this), 1000); }, }; family.callName();
|