上篇大致講解了 this 在不同狀況的指向,這篇會來講講使用 call/apply/bind 來綁定 this, 以及在嚴格模式下 this 指向會有所不同。
當我們遇上某些需求,要求 XX 函式中的 this
是某個特定物件,這時便會使用 call()
、 apply()
、bind()
來調整特性函式中的 this
。
這三個方法和 filter()
、 forEach()
一樣是藉由原型提供的,因此這三個方法,不需要任何設定便可使用,這邊先來看看範例
var name = 'Ryder'
function showName() {
console.log(this.name)
}
showName()
這是上一篇文章中 this 指向 window 的一個範例,這邊試者使用 call()
方法,並且將一個新增的物件當作參數傳入,如:
var name = 'Ryder'
var obj = {
name : 'Jack'
}
function showName(item1,item2,item3) {
console.log(this.name,item1,item2,item3) // Jack, test, {}, [0,1,2]
}
showName.call(obj,'test', {}, [0,1,2])
結果 showName
中的 this
會變成指向 obj
要注意的是使用 showName.call(obj)
他會立刻就回傳,這是因為 call()
這個方法是使用後,會立刻執行函式,並且修正函式中的 this
,順帶一題在 call()
第一個參數是用來綁定函式中 this
的,第一個參數後面的參數,則都是傳遞給原本函示的參數。
apply()
與 call()
差異則是剛剛提到的 第一個參數後面的參數部分, 其他地方完全一致,call()
第一個參數後面的參數,是接受任何型別的參數 ,而 apply()
則只能使用第二個參數,並且只能接受陣列寫法的參數,如果是陣列以外的都會跳錯。
var name = 'Ryder'
var obj = {
name : 'Jack'
}
function showName(item1,item2,item3){
console.log(this.name,item1,item2,item3)
}
showName.apply(obj,['test',{}, [0,1,2] ]) // Jack, test, {}, [0,1,2]
showName.apply(obj,'test', {}, [0,1,2]) // 跳錯
bind()
算是比較常用的,和 call()
、 apply()
不同,使用後函示並不會立刻執行,而是會回傳要替換 this 的函式,因此我們會需要再使用 ()
呼叫替換後的函式,而參數部分則和 call()
接受任何形式的參數。
var name = 'Ryder'
var obj = {
name : 'Jack'
}
function showName(item1,item2,item3){
console.log(this.name,item1,item2,item3)
}
var test = showName.bind(obj)
test('test', {}, [0,1,2])
關於 call()
、 apply()
、 bind() 還有一點要提的是,使用第一個參數綁定 this 時,若如果我們傳入的是純值,那麼被替換的 tihs
會是以建構式的方式建立。
function Fn1(){
console.log(this) //String {'test'}
}
Fn1.bind('test')()
而傳入 undefined
他則會替換成 window
function Fn1(){
console.log(this) // Window
}
Fn1.call(undefined)
關於這一點 MDN 也有解釋:
注意,它可能是一個無法在函數內看到的值:若這個函數是在非嚴苛模式( non-strict mode ), null 、undefined 將會被置換成全域變數,而原生型態的值將會被封裝
由於 JavaScript 這個語言特性,算是相對寬鬆,因此 ES5 新增 嚴格模式,用來規範 JavaScript 寫法,並對程式碼做一些限制。
若要使用嚴格模式會需要再該執行環境添加 'use strict'
的字串,如果我們直接在全域使用 'use strict'
基本上就是全部的程式碼都會變為嚴格模式。
而我們本次介紹的 this
在嚴格模式下,部分的指向也會有所變動,那麼嚴格模式下 this
有甚麼更動?
主要有三點:
window
,嚴格模式下一律都會被轉為 undefined
。call()
、 apply()
、 bind()
對 this
值做綁定時,若綁定的是純值, this
的值會是建構式,嚴格模式下則會是純值本身。call()
、 apply()
、 bind()
對 this
值做綁定時,綁定的是 undefined
、Null
,this
會是 window,嚴格模式下則會是傳入的 undefined
、Null
。簡易呼叫的範例:
var name = 'Ryder'
var array = [1,2,3]
function Fn() {
'use strict'
console.log(this) // undefined
}
Fn()
array.forEach(function(){
'use strict'
console.log(this) //undefined *3
})
this
綁定 undefined
、與純值的範例
function Fn1(){
'use strict'
console.log(this) // undefined
}
Fn1.call(undefined)
function Fn2(){
'use strict'
console.log(this) // 'test'
}
Fn2.call('test')
JavaScript 核心篇 (六角學院)