close

英文 | https://medium.com/dailyjs/5-things-to-know-about-the-this-parameter-in-javascript-c97e28230a35

翻譯 |楊小愛

this 關鍵字是 JavaScript 中最令人困惑的部分之一,本文試圖通過介紹有關它的五個重要事項來闡明其目的和用法。
1、它允許訪問同一對象上的其他屬性
在 JavaScript 中,函數可以是獨立的單元,但它們也可以用作對象的值。
考慮下一個對象。
const obj = { msg: 'Hi', logMessage: function(){}}

logMessage 屬性存儲一個函數,logMessage 是一種方法。

logMessage 函數如何訪問同一對象上的其他成員?

這是這個偽參數變得有用的地方,它允許訪問同一對象上的其他成員。

const obj = { msg: 'Hi', logMessage: function(){ console.log(this.msg); }}obj.logMessage();//'Hi'

在 logMessage 方法中,this 關鍵字用於訪問同一對象的 msg 屬性。

基本上,這就是在 JavaScript 中使用 this 關鍵字的原因,它允許訪問其他擁有或繼承的屬性。

這種行為只有一個條件,函數應該作為方法調用,而不是作為函數調用。

2、它取決於函數的調用方式而不是函數的定義位置

考慮以下訪問 this 參數的函數。

this.msg = "Parent";function logMessage(){ console.log(this.msg);}

在下一個示例中,對兩個對象使用相同的函數。

const obj = { msg: 'Hi', logMessage}const newObj = { msg: 'Hello', logMessage}

這個變量引用的對象是什麼?

這取決於函數的調用方式,而不是函數的定義位置。

當 logMessage 作為 obj 對象上的方法調用時,它引用該對象。

obj.logMessage();//'Hi'

當它作為 newObj 對象上的方法被調用時,它指向它。

newObj.logMessage();//'Hello'

請考慮以下示例,其中 logMessage 屬性存儲在 obj 對象內定義的函數。

const obj = { msg: 'Hi', logMessage: function(){ console.log(this.msg); }}

logMessage 中的 this 參數是否總是引用 obj 對象,因為它是在該對象中定義的?

答案是,NO。

下面是調用 logMessage 並使用 call 方法傳遞由 this 參數引用的不同對象的示例。

const newObj = { msg: 'Hello'}obj.logMessage.call(newObj);//'Hello'

同樣可以使用 apply 方法來完成,我們甚至可以強制它使用空對象運行,這次函數記錄未定義。

obj.logMessage.apply({});//undefined

3、與函數形式一起使用時,它指向其他東西

函數不一定是對象的一部分,它們可以是獨立的單元,因此,可以用函數形式調用。

考慮下一個例子。

const obj = { msg: 'Hi', logMessage: function(){ console.log(this.msg); }}const logMessage = obj.logMessage;logMessage();//undefined

logMessage 中的 this 不依賴於函數的定義位置,在這種情況下是在 obj 對象中。

這取決於如何調用 logMessage,在前面的示例中,logMessage 被調用為函數而不是方法。這指向了一些意想不到的東西,this.msg 給出了未定義的內容。

這是另一個例子。

const obj = { msg: '', logMessage: function(){ this.msg = 'Hi'; function logSomething(){ console.log(this.msg); } logSomething(); }}obj.logMessage();//undefined

logMessage 作為方法調用(obj.logMessage()),但 logSomething 作為函數調用。因為 logSomething 不是作為方法調用,而是作為函數調用,所以,在其中 this 指向未例外的東西。在這種情況下,this.msg 給出未定義。

如果您希望 this 引用正確的對象,請確保始終將 logMessage 作為方法調用。

4 、箭頭函數沒有this

確實箭頭函數沒有自己的 this。它們實際上是用來解決我們之前在方法內部調用內部函數時遇到的問題。

檢查下一個示例。

const obj = { logMessage: function(){ const msg = 'Hi'; const logSomething = ()=>{ console.log(msg); } logSomething(); }}obj.logMessage();//'Hi'

logSomething 是否將 msg 作為變量?不。

logSomething 在嘗試訪問它沒有的變量時會發生什麼?

它向下看它的父級元素來找到變量並使用它。

據說箭頭函數沒有自己的 this,它實際上是什麼意思?

這意味着它看不起它的父級元素來找到變量並使用它。

看下面的例子。

const obj = { msg: '', logMessage: function(){ this.msg = 'Hi'; const logSomething = ()=>{ console.log(this.msg); } logSomething(); }}obj.logMessage();//'Hi'

logSomething 沒有這個參數,與從外部環境中使用的其他變量和參數一樣,它向下查看鏈並在其父級中找到它並使用它。

logSomething 中的 this 與 logMessage 中的對象相同。

5、應用程序可以在不使用它的情況下編寫

除非應用程序已經以這種方式編寫,否則無需使用 this 關鍵字編寫應用程序。

像 React Hooks、VueJs Composition API 和 Svelte 這樣的 UI 框架允許在不使用 this 關鍵字的情況下編寫組件。

我們可以使用閉包來編寫封裝對象,這是一個例子。

const obj = (function(){ let msg = ''; function logMessage(){ msg = 'Hi'; const logSomething = ()=>{ console.log(msg); } logSomething(); } return { logMessage }})();obj.logMessage();//'Hi'

logMessage 是在自執行函數內部定義的內部函數。logMessage 是一個閉包。它從外部函數引用 msg 變量。即使在自執行函數返回後,它也可以訪問此變量。

現在它不關心我們是否將 logMessage 作為函數或作為方法調用,它總是引用正確的 msg 變量。

const logMessage = obj.logMessage;logMessage();//'Hi'

寫在最後的想法

如果您真的想使用 this 關鍵字,或者受限於應用程序內部已經做出的決定,請記住該函數應作為方法調用以指向正確的對象。

如果真的不喜歡使用 this 關鍵字,您也可以考慮使用閉包實現對象並完全避免使用 this。

好了,以上就是我今天這篇文章所要跟你分享的內容,如果您覺得有幫助的話,請記得點讚我,關注我,同時,將它與您的開發者朋友一起來分享它,也許能夠幫助到他。

學習更多技能

請點擊下方公眾號


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()