搜尋
首頁web前端js教程Javascript中的作用域和上下文深入理解_javascript技巧

概述

Javascript中的作用域和上下文的實作是Javascript語言獨有的特性,從某種程度上來說,Javascript語言是十分靈活的。 Javascript中的函數可以採用各種各樣的上下文,作用域也可以被封裝和保存。正是由於這些特性,Javascript也提供了許多很有用的設計模式。然而,作用域和脈絡也是Javascript程式設計師在開發中經常迷惑的地方。
以下會向大家介紹Javascript中作用域和上下文的概念,以及它們的不同。

作用域 VS 上下文

首先要說明的很重要的一點是作用域和上下文並不是同一個概念,它們指涉的並不是同一個東西。作為一個前端的菜逼,常常會看到一些文章把這兩個概念弄混,結果有些東西越看越不明白。這兩個概念貌似被混淆了很長一段時間了。因此,查了很多資料,簡單說明下這兩個概念。 :stuck_out_tongue_closed_eyes:
在Javascript中,當函數被呼叫時都會有一個作用域和上下文和這個函數綁定在一起。從根本上來說,作用域是基於函​​數的而上下文是基於物件的。換句話說,作用域適用於函數被呼叫時函數中變數的存取權限。上下文通常是指「this」關鍵字的值,「this」是擁有目前執行程式碼的物件的參考。

變數作用域

變數可以定義在局域或全域作用域中,分別稱為局部變數和全域變數。全域變數是指在函數體外宣告的變量,在程式的任何地方都可以存取全域變數。局部變數是指在函數體內定義的變量,它僅可以在函數體內或嵌套的函數內被訪問,並且不能在函數外部被訪問。
Javascript目前並不支援區塊級作用域(在if、switch、for等語句中定義的變數)。這意味著在區塊內定義的變量,在區塊外也可以存取。但是,在ES6中,我們可以使用「let」關鍵字來定義區塊級作用域。
關於作用域的內容,大家可以查到別的資料,這部分內容相對簡單。

「this」上下文

上下文(context)通常取決於函數被呼叫的方式。當函數作為物件的方法被呼叫時,「this」指涉的是呼叫該函數的物件。

複製程式碼 程式碼如下:

var obj={
    foo:function (){
        console.log(this === obj);
    }
};
obj.foo();   //輸出true

同樣,當我們使用「new」關鍵字建立新物件時,this引用的是新建立的物件。
複製程式碼 程式碼如下:

function foo(){
    console.log(this);
}
foo();         //輸出window
var obj=new foo();     //輸出 foo {}

有一點要注意的是,當全域作用域中的函數被呼叫時,this引用的是全域對象,在瀏覽器環境中指的就是window。但是,如果在嚴格模式下運行程式碼時,「this」被設定為「undefined」
執行上下文(Execution Context)

Javascript是單執行緒的語言,這也就是說Javascript在瀏覽器中執行時,一次只能做一件事情,其他的事情將被方法佇列中,等待被處理。

1.當Javascript程式碼檔案被瀏覽器載入後,預設最新進入的是一個全域的執行上下文。當在全域上下文中呼叫函數時,程式留就進入該被呼叫函數內,此時Javascript引擎就會為該函數建立一個新的執行上下文,並且將其壓入到執行上下文堆疊的頂部。瀏覽器總是執行當前在堆疊頂部的上下文,一旦執行完畢,該上下文就會從堆疊頂部被彈出,然後,進入其下的上下文執行程式碼。這樣,堆疊中的上下文就會被依序執行並且彈出堆疊,直到回到全域的上下文。

2.一個執行上下文可以被分成兩個階段:建立階段和執行階段。在創建階段,javascript解釋器首先會創建一個變數物件(也成為“活動物件”,activation object)。活動物件由變量,函數宣告和參數組成。在這個階段,函數的作用域鏈被初始化,this引用的物件也被確定。接下來就是執行階段,在這個階段,程式碼被解釋並執行。
在Javascript程式碼中,可以有任意多個函數上下文,我們已經知道,當函數被呼叫時,Javascript解釋器就會建立一個新的上下文,同時會建立一個私有的作用域,函數內部宣告的任何變數都不能在目前函數作用域外部直接存取。

3.透過上面的解釋,我們對函數的「執行上下文」有了一個基本的概念,但是這裡也是大家最容易迷惑的一個地方。 Javascript中的「執行上下文」主要是指作用域,而不是上面第四小節所指的「this上下文」。類似的容易混淆的概念在Javascript中還有很多,但是我們只要弄清楚了每個概念所指代的具體對象,就不會再迷惑,因此,這裡也希望大家能夠真正的區分開“執行上下文”和“this上下文”。

簡單的一句話概括來說,執行上下文是與作用域相關的概念,雖然這樣說可能不太嚴謹。

作用域鏈

對每一個執行上下文來說,都有一個作用域連跟它綁在一起。作用域鏈包含了執行上下文堆疊中的執行上下文活動物件(activation object,聽起來有點繞口)。作用域鏈決定了變數的存取和識別碼的解析。

程式碼範例:

複製程式碼 程式碼如下:

function first(){
    second();
    function second(){
        third();
        function third(){
            fourth();
            function fourth(){
                //代碼
            }
        }
    }
}
first();

執行上面的程式碼,巢狀的函數都會被執行。就上面的程式碼來說,也會形成一個作用域鏈,作用域鏈從頂部到底部的順序為:fourth, third, second, first, global。函數fourth可以存取全域作用域中的變量,並且可以存取函數third, second, first中定義的任何變數。
有一點要注意的是,在函數體內,局部變數的優先權高於同名的全域變數。如果在函數內宣告的局部變數或函數參數中帶有的變數和全域變數重名,那麼全域變數就被局部變數所覆蓋。
簡單來說,每次我們嘗試訪問一個變量時,程式都會在當前函數作用域內查找變量,如果找不到就沿著作用域鏈到該函數的上層去查找,直到找到該變量為止,如果找不到則回傳undefined。

總結

這篇文章介紹了javascript中上下文和作用域的相關概念,javascript中還有幾個比較重要的概念,如閉包等,這些在以後自己弄明白了會寫成文章~~

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
es6数组怎么去掉重复并且重新排序es6数组怎么去掉重复并且重新排序May 05, 2022 pm 07:08 PM

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

JavaScript的Symbol类型、隐藏属性及全局注册表详解JavaScript的Symbol类型、隐藏属性及全局注册表详解Jun 02, 2022 am 11:50 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

原来利用纯CSS也能实现文字轮播与图片轮播!原来利用纯CSS也能实现文字轮播与图片轮播!Jun 10, 2022 pm 01:00 PM

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

JavaScript对象的构造函数和new操作符(实例详解)JavaScript对象的构造函数和new操作符(实例详解)May 10, 2022 pm 06:16 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

javascript怎么移除元素点击事件javascript怎么移除元素点击事件Apr 11, 2022 pm 04:51 PM

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

JavaScript面向对象详细解析之属性描述符JavaScript面向对象详细解析之属性描述符May 27, 2022 pm 05:29 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

foreach是es6里的吗foreach是es6里的吗May 05, 2022 pm 05:59 PM

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。

整理总结JavaScript常见的BOM操作整理总结JavaScript常见的BOM操作Jun 01, 2022 am 11:43 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器