第二節、JavaScript 設計模式——this、call 和 apply

這一節不涉及具體設計模式,只是針對我們後續的學習做一個鋪墊,如果是對這三者很瞭解的話請跳過此節。

JavaScript 的 this 總是指向一個對象,具體指向哪個對象在運行時基於函數的執行環境動態綁定的,而非函數聲明時的環境。

除去不常用的 with 和 eval 的情況,this 的指向大致分爲以下4種:

  • 作爲對象的方法調用
  • 作爲普通函數調用
  • 構造器調用
  • Function.prototype.call 或 Function.prototype.apply 調用
1、作爲對象方法調用

如果對象的方法裏面包含thisthis指向的就是方法運行時所在的對象。該方法賦值給另外一個對象,就會改變this的指向。

let obj = {
	a:1,
	getA:()=>{
		alert(this === obj) //輸出:true
		alert(this.a) //輸出: 1
	}
}
obj.getA()
2、作爲普通函數調用

全局環境使用 this,它指的就是頂層對象 window

window.name = "globalName"

let getName = ()=>{
	return this.name
}
console.log(getName()) //輸出: globalName

// 再來看這一個
let obj = {
	name:'seven',
	getCurName:()=>{
		return this.name
	}
}
let getOtherName = obj.getCurName
console.log(getOtherName()) //輸出:globalName

上面第二個例子是不是困惑了,哈哈。再去好好讀讀本篇文章的第二段話,多讀幾遍,加深理解,函數getOtherNameconsole.log 裏面執行時所處的執行環境此時是在全局作用域內,所以 this 的指向是 window

3、作爲構造器調用

構造函數的 this ,指向實例對象。

let obj = (p)=>{
	this.p = p
}
let o = new obj('love')
console.log(o.p) //輸出:love
4、Function.prototype.call 或 Function.prototype.apply 調用

跟普通函數調用相比,這兩個調用可以動態改變傳入函數的this

let obj1 = {
	name:'seven',
	getName: ()=>{
		return this.name
	}
}
let obj2 = {
	name:'anne'
}

console.log(obj1.getName()) //輸出:seven
console.log(obj1.getName.call(obj2)) //輸出:anne

擴展一下:

綁定this的方法

也就是常用的callapplybind三個方法。
三者都可以接受多個參數;但是第一個參數是this所要指向的那個對象。區別如下:

  • callapplybind 三者第一個參數都是 this 要指向的對象,也就是想指定的上下文;
  • callapplybind 三者都可以利用後續參數傳參;
  • bind是返回對應 函數,便於稍後調用;callapply 則是立即調用 。
  • 對於 callapply 二者而言,作用完全一樣,只是接受 參數 的方式不太一樣。call 是把參數按順序傳遞進去,而 apply 則是把參數放在數組 裏。

注意點:

  • 方法的參數,應該是一個對象。如果參數爲空、null和undefined,則默認傳入全局對象。
  • 如果方法的第一個參數是一個原始值,那麼這個原始值會自動轉成對應的包裝對象,然後傳入方法。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章