如何在回撥函式內部訪問正確的“this”?


在本教程中,我們將學習如何在回撥函式內部訪問正確的“this”。

“this”關鍵字

每個函式都包含一個稱為 this 的關鍵字,也稱為“上下文”,其值由函式的呼叫方式決定,而不是由其定義方式、時間或位置決定。與其他變數不同,它不受詞法作用域的影響。與其他語言相比,JavaScript 在使用函式的“this”關鍵字時略有不同。在嚴格模式和非嚴格模式之間,還有一些其他的變化。

函式的呼叫方式通常決定“this”的值(執行時繫結)。它在每次呼叫函式時都可能改變,並且在其執行期間不能透過賦值來改變。對於函式的呼叫方式,bind() 方法可以設定此值,因為箭頭函式沒有自己的“this”繫結(它保留封閉詞法上下文的“this”值)。

什麼是回撥函式?

從另一個函式接收引數的函式稱為回撥函式,通常在外部函式中稍後使用。外部函式接受回撥函式的術語稱為高階函式。

回撥函式擁有自己的一組方法和屬性,因為在 JavaScript 中函式是物件。“this”屬性在高階函式中執行時分配給回撥函式,完全取決於回撥函式的建立方式,而不是其定義位置、方式或時間。

透過檢查呼叫回撥函式的高階函式,我們可以確定回撥函式內的“this”值。封閉函式的實際定義可能包含區域性作用域屬性,這是回撥函式中 this 問題的主要原因。但是,由於回撥函式的上下文會根據其呼叫方式動態變化,因此在透過回撥函式內的“this”繫結訪問該屬性時,該屬性不存在。

現在我們將學習在回撥函式內部訪問正確的“this”的方法。

使用“self”模式

建立一個名為 self 的變數,併為其賦予在宣告函式的作用域中的 this 值,這是一個常見的模式。我們可以透過建立一個名為 self 的新變數(任何其他有效的變數名都可以)併為其賦予“this”的值來實現所需的行為。

示例

<html>
<body>
   <h2> 'this' Inside a Callback using the <i> 'self' pattern </i> </h2>
   <button onclick="myFunction()"> Click here </button>
   <div id="root" style="
      background-color: rgb(240, 248, 255);
      border: 1px solid gray;
      margin: 5px 0px;
      padding: 10px;
   ">
      Welcome to Tutorialspoint!
   </div>
   <script>
      const root = document.getElementById('root')
      function myFunction() {
         this.variable = 'I am this variable'
         const variable = 'I am a const variable'
         const self = this
         setTimeout(() => {
            root.innerHTML = this.variable + '<br/>'
            root.innerHTML += variable
         }, 1000)
      }
   </script>
</body>
</html>

使用箭頭函式

ECMAScript 6 引入了 JavaScript 箭頭函式。它們沒有自己的繫結,並且是傳統函式表示式的更簡潔的替代方案。這確保瞭如果在箭頭函式內引用 this,則會在作用域中將其作為常規變數進行搜尋。

示例

<html>
<body>
   <h2> 'this' Inside a Callback using the <i> arrow function </i> </h2>
   <button onclick="myFunction('ABC')"> Click here </button>
   <div id="root" style="
      background-color: rgb(240, 248, 255);
      border: 1px solid gray;
      margin: 5px 0px;
      padding: 10px;
   ">
      Welcome to Tutorialspoint!
   </div>
   <script>
      const root = document.getElementById('root')
      function myFunction(name) {
         this.name = name
         let obj = {
            run: function(callback) {
               setTimeout(callback, 1000)
            },
         }
         obj.run(() => {
            root.innerHTML = this.name
         })
      }
   </script>
</body>
</html>

使用另一個變數儲存“this”物件

物件連結到它,這通常是我們嘗試在回撥函式內部訪問 this 時真正想要訪問的內容。一種方法是在回撥函式作用域之前建立一個變數並存儲其值(儘管一些程式設計師可能不願意這樣做,因為它看起來很混亂)。

有些人稱之為 that 或 self,但只要術語清晰,名稱並不重要。此解決方法有效,因為該變數符合詞法作用域要求,因此在回撥函式內可用。您仍然可以訪問回撥函式的動態 this 繫結,這是此方法的額外好處。

示例

<html>
<body>
   <h2>
      'this' Inside a Callback using the
      <i> another variable to store the 'this' object </i>
   </h2>
   <button onclick="myFunction('XYZ')"> Click here </button>
   <div id="root" style="
      background-color: rgb(240, 248, 255);
      border: 1px solid gray;
      margin: 5px 0px;
      padding: 10px;
   ">
      Welcome to Tutorialspoint!
   </div>
   <script>
      const root = document.getElementById('root')
      function myFunction(name) {
         this.name = name
         let that = this
         let obj = {
            run: function(callback) {
               setTimeout(callback, 1000)
            },
         }
         obj.run(function() {
            root.innerHTML = this.name
         })
      }
   </script>
</body>
</html>

顯式地將 this 繫結到物件

當我們定義回撥函式時,我們可以宣告我們希望 this 是什麼。我們可以使用 bind() 方法設定“this”值,並確保無論函式如何或在何處呼叫或傳遞,它都將保持不變。

bind() 方法在每個函式中都可用,並建立一個新的函式,其“this”屬性連線到給定的物件。返回的函式和原始函式之間的唯一區別是您可以完全控制“this”屬性指向的內容。

示例

<html>
<body>
   <h2>
      'this' Inside a Callback using
      <i> explicitly binding this to an object </i>
   </h2>
   <button onclick="myFunction('Tutorialspoint')"> Click here </button>
   <div id="root" style="
      background-color: rgb(240, 248, 255);
      border: 1px solid gray;
      margin: 5px 0px;
      padding: 10px;
   ">
      Welcome to Tutorialspoint!
   </div>
   <script>
      const root = document.getElementById('root')
      function myFunction(name) {
         this.name = name
         let callbackFunction = function() {
            root.innerHTML = this.name
         }.bind(this)
         let obj = {
            run: function(callbackFunction) {
               setTimeout(callbackFunction, 1000)
            },
         }
         obj.run(callbackFunction)
      }
   </script>
</body>
</html>

更新於:2022-12-06

491 次瀏覽

啟動你的職業生涯

完成課程獲得認證

開始學習
廣告
© . All rights reserved.