iT邦幫忙

3

Day [4] — this:指定物件 — JS之浸豬籠系列

  • 分享至 

  • twitterImage
  •  

Day [4] — this:指定物件 — JS之浸豬籠系列

我們在前面幾章知道 this 會依據呼叫方式印出不同結果,那如果我們希望可以存取 this 的某個特定內容呢?要指定 this 取得其內容有幾種方法:

設定變數:重新指向 this

//來個範例!
//記得用回推的方式看會比較清楚

function callName() {
  console.log('區域', this.name); //這裡會印出區域結果

  var that = this; //讓that變數 = this 在被呼叫時間點的值

  setTimeout(function () {
    console.log('全域', this.name); 
		//上一章我們提過,這裡會從全域(Window)去尋找

    console.log('區域', that.name); 
		// 因為我們已經指定 that,所以只會去尋找被呼叫時間點的值
  }, 10);
}

var name = '全域阿婆';	//全域(Window)

var auntie = { //區域(這裡的 function 指向全域的 function,但不重要)
  name: '漂亮阿姨',
  callName: callName
  
}

auntie.callName();
//我們呼叫 auntie 裡的 callName,
//callName =  function callName,所以他將會印出以下三行的結果:
	//console.log('區域', this.name);
	//console.log('全域', this.name); 
	//console.log('區域', that.name); 

//////////////解析一下

**//第一個:console.log('區域', this.name);
//印出: 區域 漂亮阿姨**

//我們將這裡的 this.name 回推,往外看 第一個先看到  function callName
//function callName 是 var auntie 裡的物件 callName: callName
//所以這裡的 this是指向 auntie ,而 auntie裡的name是 漂亮阿姨
//故就會印出  區域 漂亮阿姨

**//第二個:console.log('全域', this.name);
//印出: 全域 全域阿婆**

//一樣我們將這裡的 this.name 回推, setTimeout(function () 
//是切分變數的最小範圍(也就是scope),故this 往外推的時候指向全域(window)
//所以他會找到的是 var name = '全域阿婆';
//故印出 全域 全域阿婆

//**第三個:console.log('區域',** that.name**);
//印出: 區域 漂亮阿姨**

//我們在 function callName() 中指定 var that = this;
//記得我們是以 auntie.callName();的方式呼叫的
//所以結果就會跟 第一個 一樣

設一個 變數 = this

如果你看懂上面了,應該會想說 that 一定要寫 that 嗎?
其實並不用,這裡的變數名稱可以自己指定,例如一般常用的 a 或其他自訂名稱都可以。

var that = this ;
//that可以替換成任意的自訂名稱

除了設定變數以外還有其他方式可以指定 this 嗎?

有三個方式可以使用,分別是 bind() / call() / apply()

.bind()

產生副本,藉由副本讀取資料

 //來個範例吧!

var obj = {
		x : 123,
}
//obj物件中,x的值是123

var func = function(){
		console.log(this.x);
}

func(); //這裡我們嚴格指定 var func = function(),故 undefiend

func.bind(obj); //當我們使用 .bind(obj),會替我們將 this 指向 obj ,故得123

.call()

.call() 調用的函式可以直接傳入新的物件,使其作為 this 所指向的物件。

 //來個範例吧!

var name = '全域阿婆';

function callName() {
  console.log(this.name);
}

callName();                        
// 去尋找了全域,故印出'全域阿婆'

callName.call({name: '漂亮阿姨'});  
// 這邊直接將this指向'漂亮阿姨','漂亮阿姨'作為物件被傳入 callName 中

.apply()

.apply() 調用的函式可以直接傳入新的物件,使其作為 this 所指向的物件。

var name = '全域阿婆';
function callName() {
  console.log(this.name);
}

callName();                        
// 去尋找了全域,故印出'全域阿婆'

callName.apply({name: '漂亮阿姨'});  
// 這邊直接將this指向'漂亮阿姨','漂亮阿姨'作為物件被傳入 callName 中

....等等,先聽我解釋!(鼻要打臉)

.call() 和 .apply() 的區別

//來個範例吧!

function add(c, d) {
  return this.a + this.b + c + d;
}

var o = {
		a: 1, 
		b: 3
};

add.call(o, 5, 7); // 16
// 第一個參數(parameter)是調用了 this 的物件,
// 後續參數(parameters)會作為函式呼叫內的參數(arguments)而通過

add.apply(o, [10, 20]); // 34
// 第一個參數(parameter)是調用了 this 的物件,
// 第二個參數的陣列作為函式呼叫內的參數(arguments)之構件

.call() 和 .apply() 的區別就在於傳入的方式,.call()傳入參數的方式是以 『 , 』隔開,而 .apply() 則是傳入整個陣列作為參數。


bind / call / apply

bind(綑綁)

產生副本,藉由副本讀取資料。
bind 會在呼叫前就先綁定某個物件(類似產生副本),讓他不管怎麼呼叫都有固定的 this。

call (呼叫)/ apply(應用)

使用在 context 時常變動的場景(例如上面的範例 o 就是 context ),依照呼叫時需要帶入不同物件作為該 function 的 this ,在呼叫下就立即執行。


引用及參考資訊
鐵人賽:JavaScript 的 this 到底是誰?

MDN : this

淺談 JavaScript 頭號難題 this:絕對不完整,但保證好懂

What's THIS in JavaScript ? [上]


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
1
pokaeatlunch
iT邦新手 5 級 ‧ 2022-07-07 01:23:31

物換星移,人事已非,學姊叫我發,怎麼敢不發

1
紅茶小公主
iT邦新手 2 級 ‧ 2022-07-07 01:23:45

1th 搶頭香
讚讚讚
Poka 豪棒ㄛ~~~

0
diandian0228
iT邦新手 5 級 ‧ 2023-07-12 09:42:57

時隔一年
敲碗Day5

我要留言

立即登入留言