中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript函數執行上下文的this怎么調用

發布時間:2022-10-26 09:55:10 來源:億速云 閱讀:136 作者:iii 欄目:開發技術

今天小編給大家分享一下JavaScript函數執行上下文的this怎么調用的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

    JavaScript 中的 this 是什么

    關于 this,我們得先從執行上下文說起。我們知道:執行上下文中包含了變量環境、詞法環境、外部環境,當然也包括 this,具體你可以參考下圖:

    JavaScript函數執行上下文的this怎么調用

    從圖中可以看出,this 是和執行上下文綁定的,也就是說每個執行上下文中都有一個 this。執行上下文主要分為三種——全局執行上下文、函數執行上下文和 eval 執行上下文,所以對應的 this 也只有這三種——全局執行上下文中的 this、函數中的 this 和 eval 中的 this。

    不過由于 eval 我們使用的不多,所以本文我們對此就不做介紹了,如果你感興趣的話,可以自行搜索和學習相關知識。

    那么接下來我們就重點講解下全局執行上下文中的 this和函數執行上下文中的 this。

    全局執行上下文中的 this

    首先我們來看看全局執行上下文中的 this 是什么。

    你可以在控制臺中輸入console.log(this)來打印出來全局執行上下文中的 this,最終輸出的是 window 對象。所以你可以得出這樣一個結論:全局執行上下文中的 this 是指向 window 對象的。這也是 this 和作用域鏈的唯一交點,作用域鏈的最底端包含了 window 對象,全局執行上下文中的 this 也是指向 window 對象。

    函數執行上下文中的 this

    現在你已經知道全局對象中的 this 是指向 window 對象了,那么接下來,我們就來重點分析函數執行上下文中的 this。還是先看下面這段代碼:

    function foo() {
      console.log(this);
    }
    foo();

    我們在 foo 函數內部打印出來 this 值,執行這段代碼,打印出來的也是 window 對象,這說明在默認情況下調用一個函數,其執行上下文中的 this 也是指向 window 對象的。估計你會好奇,那能不能設置執行上下文中的 this 來指向其他對象呢?答案是肯定的。通常情況下,有下面三種方式來設置函數執行上下文中的 this 值。

    1. 通過函數的 call 方法設置

    你可以通過函數的call方法來設置函數執行上下文的 this 指向,比如下面這段代碼,我們就并沒有直接調用 foo 函數,而是調用了 foo 的 call 方法,并將 bar 對象作為 call 方法的參數。

    let bar = {
      myName: " name1 ",
      test1: 1,
    };
    function foo() {
      this.myName = " name2 ";
    }
    foo.call(bar);
    console.log(bar);
    console.log(myName);

    執行這段代碼,然后觀察輸出結果,你就能發現 foo 函數內部的 this 已經指向了 bar 對象,因為通過打印 bar 對象,可以看出 bar 的 myName 屬性已經由“name1”變為“name2”了,同時在全局執行上下文中打印 myName,JavaScript 引擎提示該變量未定義。

    其實除了 call 方法,你還可以使用bind和apply方法來設置函數執行上下文中的 this,僅僅是語法稍有不同。

    2. 通過對象調用方法設置

    要改變函數執行上下文中的 this 指向,除了通過函數的 call 方法來實現外,還可以通過對象調用的方式,比如下面這段代碼:

    var myObj = {
      name: " name ",
      showThis: function () {
        console.log(this);
      },
    };
    myObj.showThis();

    在這段代碼中,我們定義了一個 myObj 對象,該對象是由一個 name 屬性和一個 showThis 方法組成的,然后再通過 myObj 對象來調用 showThis 方法。執行這段代碼,你可以看到,最終輸出的 this 值是指向 myObj 的。

    所以,你可以得出這樣的結論:使用對象來調用其內部的一個方法,該方法的 this 是指向對象本身的。

    其實,你也可以認為 JavaScript 引擎在執行myObject.showThis()時,將其轉化為了:

    myObj.showThis.call(myObj)

    接下來我們稍微改變下調用方式,把 showThis 賦給一個全局對象,然后再調用該對象,代碼如下所示:

    var myObj = {
      name: " time ",
      showThis: function () {
        this.name = " bang ";
        console.log(this);
      },
    };
    var foo = myObj.showThis;
    foo();

    執行這段代碼,你會發現 this 又指向了全局 window 對象。

    所以通過以上兩個例子的對比,你可以得出下面這樣兩個結論:

    • 在全局環境中調用一個函數,函數內部的 this 指向的是全局變量 window。

    • 通過一個對象來調用其內部的一個方法,該方法的執行上下文中的 this 指向對象本身。

    3. 通過構造函數中設置

    你可以像這樣設置構造函數中的 this,如下面的示例代碼:

    function CreateObj() {
      this.name = " time ";
    }
    var myObj = new CreateObj();

    在這段代碼中,我們使用 new 創建了對象 myObj,那你知道此時的構造函數 CreateObj 中的 this 到底指向了誰嗎?

    其實,當執行 new CreateObj() 的時候,JavaScript 引擎做了如下四件事:

    • 首先創建了一個空對象 tempObj;

    • 接著調用 CreateObj.call 方法,并將 tempObj 作為 call 方法的參數,這樣當 CreateObj 的執行上下文創建時,它的 this 就指向了 tempObj 對象;

    • 然后執行 CreateObj 函數,此時的 CreateObj 函數執行上下文中的 this 指向了 tempObj 對象;

    • 最后返回 tempObj 對象。

    這樣,我們就通過 new 關鍵字構建好了一個新對象,并且構造函數中的 this 其實就是新對象本身。

    this 的設計缺陷以及應對方案

    就我個人而言,this 并不是一個很好的設計,因為它的很多使用方法都沖擊人的直覺,在使用過程中存在著非常多的坑。下面咱們就來一起看看那些 this 設計缺陷。

    1. 嵌套函數中的 this 不會從外層函數中繼承

    我認為這是一個嚴重的設計錯誤,并影響了很多開發者。

    至于如何解決?你可以在函數中聲明一個變量 self 用來保存 this。當然也可以使用 ES6 中的箭頭函數來解決這個問題。

    2. 普通函數中的 this 默認指向全局對象 window

    上面我們已經介紹過了,在默認情況下調用一個函數,其執行上下文中的 this 是默認指向全局對象 window 的。

    不過這個設計也是一種缺陷,因為在實際工作中,我們并不希望函數執行上下文中的 this 默認指向全局對象,因為這樣會打破數據的邊界,造成一些誤操作。如果要讓函數執行上下文中的 this 指向某個對象,最好的方式是通過 call 方法來顯示調用。

    這個問題可以通過設置 JavaScript 的“嚴格模式”來解決。在嚴格模式下,默認執行一個函數,其函數的執行上下文中的 this 值是 undefined,這就解決上面的問題了。

    以上就是“JavaScript函數執行上下文的this怎么調用”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    霍山县| 明水县| 洱源县| 洪湖市| 临夏县| 金坛市| 岢岚县| 东乌| 毕节市| 永和县| 玉门市| 于都县| 建平县| 合川市| 合肥市| 广汉市| 新建县| 城口县| 左云县| 西华县| 门源| 济南市| 合作市| 始兴县| 勃利县| 玛纳斯县| 新乐市| 庆安县| 保靖县| 衡南县| 双桥区| 咸丰县| 马鞍山市| 沾化县| 肃南| 临清市| 东明县| 佳木斯市| 正定县| 灵台县| 宜川县|