突然頓悟的Javascript中的this

来源:http://www.cnblogs.com/smiler/archive/2016/06/23/5610056.html
-Advertisement-
Play Games

一直對Javascript中的this都有一種似是而非的感覺,今天突然感覺豁然開朗,特此記錄一下。 咱們先看個慄子: 咋一看這段代碼沒有什麼問題,但是由於對於this的錯誤理解最終導致錯誤的結果。我們在元素car_key上面綁定了click事件,認為在car的類中嵌套綁定click事件就可以讓這個d ...


  一直對Javascript中的this都有一種似是而非的感覺,今天突然感覺豁然開朗,特此記錄一下。

咱們先看個慄子:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>this的使用</title>
        <script type="text/javascript">
            var Car,tesla;
            Car=function  () {
                this.start=function(){
                    console.log('car started');
                };
                this.turnKye=function () {
                    var carKey=document.getElementById('car_key');
                    carKey.onclick=function () {
                    this.start();    
                    };
                }
                return this;
            }
            
            tesla=new Car();
            tesla.turnKye();
        </script>
    </head>
    <body>
      <input type="button" id="car_key" value="test" />
        
    </body>
</html>

      咋一看這段代碼沒有什麼問題,但是由於對於this的錯誤理解最終導致錯誤的結果。我們在元素car_key上面綁定了click事件,認為在car的類中嵌套綁定click事件就可以讓這個dom元素訪問car的this上下文。這種方式看起來很合理,但是不幸的是它並不工作。

在Javascript中,this關鍵字總是指向正執行的作用域的所有者。

  請大家仔細揣摩上面那句話。正如我們所知,函數調用會產生新的作用域,一點onclick事件被觸發,this就指向了dom元素而不是Car的類。

  那我們怎麼做才會讓它能正常工作呢?我們通常會把this賦值給一個局部的自由變數(比如that,_this,self,me等,這個在許多的框架裡面都有體現)來避開作用域帶來的問題。這裡使用局部變數來重寫之前的方法:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>this的使用</title>
        
    </head>
    <body>
      <input type="button" id="car_key" value="test" />
        <script type="text/javascript">
            var Car,tesla;
            Car=function  () {
                this.start=function(){
                    console.log('car started');
                };
                this.turnKye=function () {
                    var that=this;
                    var carKey=document.getElementById('car_key');
                    
                    carKey.onclick=function () {
                      that.start();    
                    };
                }
                return this;
            }
            
            tesla=new Car();
            tesla.turnKye();
        </script>
    </body>
</html>

  由於that是一個自由變數,onclick事件的出發並不會引起它的重新定義。

   如果你熟悉ES6的話可以使用胖箭頭符號,這更簡潔和更容易理解,如下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>this的使用</title>
        
    </head>
    <body>
      <input type="button" id="car_key" value="test" />
        <script type="text/javascript">
            var Car,tesla;
            Car=function  () {
                this.start=function(){
                    console.log('car started');
                };
                this.turnKye=function () {
                    //var that=this;
                    var carKey=document.getElementById('car_key');
                    
                    //carKey.onclick=function () {
                     // that.start();    
                    //};
                    carKey.onclick=()=>this.start();
                }
                return this;
            }
            
            tesla=new Car();
            tesla.turnKye();
        </script>
    </body>
</html>

當然我們也可以使用綁定函數的方法來解決這個問題:如下

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>this的使用</title>
        
    </head>
    <body>
      <input type="button" id="car_key" value="test" />
        <script type="text/javascript">
            var Car,tesla;
            Car=function  () {
                this.start=function(){
                    console.log('car started');
                };
                
                var click=function(){
                    this.start();    
                }
                this.turnKye=function () {
                    //var that=this;
                    var carKey=document.getElementById('car_key');
                    
                    carKey.onclick=click.bind(this);
                
                }
                return this;
            }
            
            tesla=new Car();
            tesla.turnKye();
        </script>
    </body>
</html>

其實這些在學習React的時候,綁定事件的時候遇到的坑,那時候只知道這麼寫,不知道怎麼回事,今天突然感覺豁然開朗。希望對大家有所幫助。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 這篇文章主要介紹了C++實現郵件群發的方法,較為詳細的分析了郵件發送的原理與C++相關實現技巧,非常具有實用價值,需要的朋友可以參考下 本文實例講述了C++實現郵件群發的方法。分享給大家供大家參考。具體如下:關於生成隨機QQ郵箱不精確的問題,在之後版本打算另寫一個採集器插件進行帳號採集,所以,這個軟 ...
  • 今天又看了下Hangout的源碼,一般來說一個開源項目有好幾種啟動方式——比如可以從命令行啟動,也可以從web端啟動。今天就看看如何設計命令行啟動... Apache Commons CLI Apache Commons CLI是開源的命令行解析工具,它可以幫助開發者快速構建啟動命令,並且幫助你組織 ...
  • 在牛客網上刷題的時候看見這麼一道題 這很明顯是對我對父子執行流的嚴峻考察,很好,我喜歡,然後我錯了。。。騰訊實習生招聘的時候線上筆試題也有類似的題目,不過是把-換成可hello world而已,可見還是蠻重要的。這種題目只要畫一下圖很快就能理解了 顯而易見的6次 貼出結果 那麼接下來來個升級版的 執 ...
  • 在項目中我們有時候會為集合類型設定一些預設的值,使用spring後,我們可以通過配置文件的配置,用setter方式為對象的集合屬性提供一些預設值,下麵就是一個簡單的例子。 首先我們創建了一個名為Collection的類,這個類中包含四中基本的集合屬性,實現屬性的set方法和覆蓋toString()方 ...
  • 參考http://blog.csdn.net/yaopeng_2005/article/details/6935235 對小鵬_加油的代碼進行了部分修改,並加入了自己的文檔註釋 定義全局變數,以及主函數main 初始化變數Init函數 銀行家演算法Bank函數 安全性演算法Safe函數 顯示showda ...
  • 最近新做的一個項目需要使用qt5連接另一臺機器上的sql server,雖然網上已有類似文章,但還是有些其中很少提及的問題,故在這裡彙總下: qt連接sql server可以參考這篇文章: 《Qt 使用ODBC driver 連接SQL Server》 如果是連接另一臺機器的sql server就不 ...
  • **MVP模式結構** - Model: 業務邏輯和實體模型 - View:用戶交互和視圖顯示,在android中對應activity - Presenter: 負責完成View於Model間的邏輯和交互 ...
  • 最近一同事在學習AngularJS,在路由與模板的學習過程中遇到了一些問題,於是今天給她寫了個例子,順便分享出來給那些正在學習AngularJS的小伙伴們。 話說這AngularJs 開發項目非常的爽,其中爽就爽在它的開發模式,使得代碼更加的清晰、更加具有可讀性、更簡潔、更具有維護性。但是在使用An ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...