iT邦幫忙

2021 iThome 鐵人賽

DAY 29
0
自我挑戰組

JavaScript老學徒筆記—馬步篇系列 第 33

「this」好七怪!

聽前輩說,「this」在JavaScript裡面是一個大坑。

前面有提過「this」在事件監聽中,不考慮事件冒泡的情況下,this就等同是e.target,但是如果是被事件冒泡觸發的this則為e.currentTarget。

現在來談談「this」在其他地方要注意的事情。

首先要記住這句話,只要理解這個原則,大部分遇到「this」的狀況都可以輕鬆掌握:

「this代表的是function執行時所屬的物件,而不是function本身」

「this」是在函式被呼叫的時候被自動生成的內部物件,this不等於function,隨著呼叫函示的物件不同,「this」所指向的值也不同。

沒有特別指定this的情況下,this預設綁定(Default Binding)「全域物件」,也就是window

但在ES5的嚴格模式下,禁止this自動指定為全域物件,這點要特別注意。

var seven = "江南七怪";
console.log(window.seven); //"江南七怪"
function monster(){
  console.log(this.seven + "脾氣古怪");
  
}
monster();  //"江南七怪脾氣古怪"

var obj = {
  seven : "七喜汽水",
  func: monster
} 

obj.func(); //"七喜汽水脾氣古怪"

所以在全域環境中直接呼叫monster()函式時,this.seven是指向全域變數的var seven = "江南七怪";當monster()作為obj物件func屬性的方法的時候,this.seven會指向obj物件的seven屬性"七喜汽水"。

var seven = "江南七怪";
var call = function() {
	console.log(this.seven);
}

var soda = function(){
	let seven = "七喜汽水";
	this.call();
}

soda(); //"江南七怪"

soda()透過this.call()來叫用call(),這時call()裡面的this.seven是指向全域變數的seven,所以得到的結果是"江南七怪"。

如何強制指定this

在JavaScript有三種方式可以強制指定this給function,這種方式也叫「顯式綁定」,分別是:

  • .call()
  • .apply()
  • .bind()

先來說說.call與.apply

function funcA(){
	//做某件大事
}
funcA.call(context, arg1, arg2...)
funcA.apply(context,[arg1,arg2...])

上面的程式碼式使用.call與.apply去呼叫執行funcA,第一個參數context為所帶入的物件,也就是強制用那個物件來當成function執行時的物件。

.call與.apply作用一樣,差別在.apply第一個參數(帶入的物件)之後的參數以陣列方式傳入,而.call則是使用逗號隔開。

let kuo = {
	name: "郭靖",
	wife: "黃蓉"
}

let yung = {
	name: "楊過",
	wife: "小龍女"
}

function funcA(){
	console.log(`${this.name}的老婆是${this.wife}`)
}

funcA.call(kuo) //郭靖的老婆是黃蓉
funcA.apply(yung) //楊過的老婆是小龍女

funcA.call(null,"周伯通","瑛姑")//的老婆是undefined 

我們可以看見this.name與this.wife綁定到帶入的物件上。而this隨著所帶入的物件不同,指向也會動態地改變。

而bind的用法如下:

let kuo = {
	name: "郭靖",
	wife: "黃蓉"
}

let yung = {
	name: "楊過",
	wife: "小龍女"
}

function funcA(){
	console.log(`${this.name}的老婆是${this.wife}`)
}

let kuoWife = funcA.bind(kuo);
kuoWife()  //郭靖的老婆是黃蓉

let yungWife = funcA.bind(yung);
yungWife() //楊過的老婆是小龍女

藉由‵let kuoWife = funcA.bind(kuo) ‵也可以把this指向所帶入的物件。

其實以上的應用,萬變不離其宗,只要記得:「this代表的是function執行時所屬的物件,而不是function本身」


上一篇
暗通款曲的閉包
下一篇
好記性的瀏覽器:localStorage
系列文
JavaScript老學徒筆記—馬步篇35

尚未有邦友留言

立即登入留言