国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

JavaScript作用域詳解

這篇具有很好參考價值的文章主要介紹了JavaScript作用域詳解。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

目錄

前言

什么是作用域

作用域類型

全局作用域

局部作用域

塊級作用域

ES6之前

ES6以后

作用域鏈

變量提升

基礎概念

優(yōu)先級問題

閉包

定義

特點

使用場景

封裝私有變量

延長變量周期

模塊化、命名空間

緩存

ES6的作用域

const、let

塊級作用域

變量提升

暫時性死區(qū)

不可重復聲明

箭頭函數(shù)

題外話

動態(tài)作用域與詞法作用域

詞法作用域

動態(tài)作用域

總結


前言

作用域是JavaScript中一個重要的概念,它決定了變量和函數(shù)在代碼中的可訪問性和可見性。了解JavaScript的作用域對于編寫高效、可維護的代碼至關重要。本文將深入介紹JavaScript作用域相關的知識點,其中包括作用域類型,作用域鏈,變量提升以及閉包等。

什么是作用域

在之前的文章中我們對TS中的模塊進行了詳細的分享,TS的在防止命名污染,沖突時采用的是命名空間,當我們看過TS命名空間的編譯產(chǎn)物后我們就會知道,實際上其實際做法是采用JS的作用域實現(xiàn)一個獨立的區(qū)域達到解決命名沖突和變量訪問的可見性作用

JS中的作用域是一個存儲變量、函數(shù)以及對象的位置,每個變量、函數(shù)和對象都被存儲在一個特定的作用域中,它是指變量和函數(shù)在代碼中的可訪問范圍,作用域決定了代碼中哪些部分可以訪問特定的變量和函數(shù),通過作用域,我們可以將變量和函數(shù)封裝在不同的作用域中,使其在合適的范圍內(nèi)可訪問

JavaScript作用域詳解,JavaScript,面試文檔,Node.js,javascript,開發(fā)語言,前端,面試,原力計劃

就像上圖中的示例,F(xiàn)oo1無法獲取Foo2中的var4變量

作用域類型

常見的作用域類型包括全局作用域(Global Scope)、局部作用域(Local Scope)和塊級作用域(Block Scope),JS也不例外

全局作用域

全局作用域是在整個代碼中都可訪問的作用域。在瀏覽器環(huán)境中,全局作用域通常是指window對象;在node環(huán)境下,則是globalThis或global

在全局作用域中聲明的變量或函數(shù)是全局變量或全局函數(shù),在代碼任何地方都可以訪問和使用

JavaScript作用域詳解,JavaScript,面試文檔,Node.js,javascript,開發(fā)語言,前端,面試,原力計劃

比如上面圖示中的Foo4可以訪問到全局作用域的變量及函數(shù)

const var1 = "var1";
const var2 = "var2";
function Foo1() {
  const var3 = "var3";
}
function Foo2() {
  const var4 = "var4";
  function Foo3() {}
}

function Foo4() {
  console.log(var1, var2, Foo1, Foo2); // var1 var2 [Function: Foo1] [Function: Foo2]
}
Foo4();

局部作用域

JS中的局部作用域一般代指函數(shù)作用域(Function Scope),它是在函數(shù)內(nèi)部聲明的作用域,函數(shù)內(nèi)部的變量和函數(shù)只能在函數(shù)內(nèi)部訪問,外部無法直接訪問

JavaScript作用域詳解,JavaScript,面試文檔,Node.js,javascript,開發(fā)語言,前端,面試,原力計劃

就像上述Foo3的效果,可以訪問到全局以及當前所在函數(shù)的作用域的變量及函數(shù)

const var1 = "var1";
const var2 = "var2";
function Foo1() {
  const var3 = "var3";
}
function Foo2() {
  const var4 = "var4";
  function Foo3() {
    console.log(var4, Foo3); // var4 [Function: Foo3]
  }
  Foo3();
}
Foo2();

塊級作用域

塊級作用域是在代碼塊(通常是由大括號{}包裹起來的部分)內(nèi)聲明的作用域。比如if(){...}、for(...){...}、try{...}等

ES6之前

在ES6之前,由于變量都是使用var聲明的,所以沒有塊級作用域此類概念,只有全局作用域和函數(shù)(局部)作用域。那么需要模擬塊級作用域如何怎么操作呢?

答案是使用立即執(zhí)行函數(shù)表達式(IIFE):通過將代碼包裝在匿名函數(shù)中并立即執(zhí)行該函數(shù),可以創(chuàng)建一個獨立的作用域,使得內(nèi)部聲明的變量在函數(shù)外部不可訪問

(function () {
  var var5 = "var5";
  console.log(var5); // var5
})();
console.log(var5); // var5 is not defined

ES6以后

在es6以后,官方推出了塊級作用域的概念,使用let和const關鍵字聲明的變量具有塊級作用域,它們只能在聲明的代碼塊內(nèi)部訪問。

if (true) {
  let var5 = "var5";
  console.log(var5); // var5
}
console.log(var5); // var5 is not defined

作用域鏈

作用域鏈(Scope Chain)是JS用于解析標識符(變量和函數(shù))的機制,它是由多個嵌套的作用域組成的,它決定了變量和函數(shù)的查找順序。

上面我們說到局部作用域時談到的Foo3可以訪問全局以及當前函數(shù)作用域中的標識符這個特點就歸功于作用域鏈這個概念。當訪問一個變量時,JS引擎會先從當前作用域開始查找,如果找不到這個名稱的標識符則繼續(xù)向上一級作用域查找,直到找到變量或達到全局作用域為止,如果在全局作用域中仍然找不到,則認為該標識符未定義。

變量提升

變量提升的概念出現(xiàn)在面試題中的頻率十分高,對于開發(fā)者來說也是不可忽略的重要知識點;在之前的面試題文章中的Q6和Q7兩題中就出現(xiàn)了變量提升相關的知識點

基礎概念

變量提升是JS在代碼執(zhí)行前將變量和函數(shù)聲明提升到作用域頂部的行為,它由JavaScript引擎在代碼執(zhí)行前的編譯階段處理。變量提升影響了整個作用域范圍內(nèi)的代碼,它允許我們在聲明之前使用變量,但是需要注意一點:只有變量聲明被提升,賦值不會提升。了解了上述概念后,我們思考下面的代碼:

console.log(var6); // undefined
var var6 = 10;

上面的代碼相當于

var var6;
console.log(var6); // undefined
var6 = 10;

優(yōu)先級問題

當同一個作用域中同時出現(xiàn)同名的函數(shù)和變量時,函數(shù)提升的優(yōu)先級更高,也就是說函數(shù)會在變量之上聲明,參考下面的代碼

var a = 10;
function a() {}
console.log(a); // 10

可以看成是

var a; // 函數(shù)a
var a; // 變量a
a = function () {};// 使用function聲明函數(shù)可以看成是聲明+賦值
a = 10;
console.log(a); // 10

何以見得?思考以下代碼

function a() {}
var a;
console.log(a); // [Function: a]

當把a的賦值去除時,函數(shù)的賦值順序就可以得到驗證,相當于:

var a; // 函數(shù)a
var a; // 變量a
a = function () {};
console.log(a); // [Function: a]

閉包

定義

在介紹垃圾回收和內(nèi)存變化的文章時,我們提到了堆棧內(nèi)存管理的原理。當函數(shù)開始執(zhí)行時,函數(shù)中的變量以及函數(shù)會壓入棧中,那么此時如果當前的作用域中有另一個函數(shù)正在使用該作用域的變量,該變量占用的內(nèi)存也不會被垃圾回收機制回收,這個現(xiàn)象就是閉包

換句話說,閉包是指函數(shù)能夠"記住"并訪問其創(chuàng)建時的詞法環(huán)境,在函數(shù)定義的詞法作用域之外執(zhí)行同樣適用

JavaScript作用域詳解,JavaScript,面試文檔,Node.js,javascript,開發(fā)語言,前端,面試,原力計劃

思考以下代碼

const foo = (function iife() {
  const num = 10;
  function foo() {
    return num;
  }
  return foo;
})();
console.log(foo()); // 10

上述代碼中使用立即執(zhí)行函數(shù)iife作為外部函數(shù)的作用域,它返回內(nèi)部函數(shù)foo,而foo函數(shù)使用了iife函數(shù)中的num變量,形成了閉包,最后在iife函數(shù)的外部使用foo時依然可以訪問num變量

特點

  • 即使外部函數(shù)已經(jīng)執(zhí)行完畢,內(nèi)部函數(shù)依然可以訪問外部函數(shù)作用域中的變量(當棧將函數(shù)彈出時,變量依然處于內(nèi)存中)
  • 閉包可以持有對外部變量的引用,使得外部變量的值在內(nèi)部函數(shù)中保持活動狀態(tài)(不被垃圾回收機制回收)
  • 閉包中的內(nèi)部函數(shù)可以修改并更新外部變量的值
  • 閉包的函數(shù)可以獲取到創(chuàng)建時的整個作用域鏈的標識符
  • 閉包可能會導致內(nèi)存泄漏,被閉包引用的變量無法被垃圾回收機制處理

使用場景

封裝私有變量

JS中沒有TS的private關鍵詞,無法直接定義私有變量,但是可以通過閉包產(chǎn)生私有環(huán)境作用域(ES2022后引入了#關鍵字,用于定義私有變量,相比于使用閉包,更直觀和方便)

const Animal = (function () {
  const name = "dog";
  function Animal() {}
  Animal.prototype.getName = function () {
    return name;
  };
  return Animal;
})();
console.log(new Animal().getName()); // dog

延長變量周期

延長變量的生命周期也是閉包的特性之一,該效果通過內(nèi)部函數(shù)對外部作用域的可訪問性實現(xiàn)

function delayMessage(msg) {
  return function () {
    return msg;
  };
}
const msg = delayMessage("msg");
console.log(msg()); // msg

模塊化、命名空間

在TypeScript模塊文章中我們使用JS中的立即執(zhí)行函數(shù)實現(xiàn)了命名空間功能,達到模塊化的效果

var moduleA = (function () {
  var privateVariable = "Hello";
  // 私有函數(shù)
  function privateMethod() {
    console.log(privateVariable);
  }
  return {
    // 公共函數(shù)
    publicMethod: function () {
      privateMethod();
    },
  };
})();

moduleA.publicMethod(); // Hello
console.log(moduleA.privateVariable); // undefined

緩存

閉包還可以用于創(chuàng)建緩存函數(shù),以提高函數(shù)的執(zhí)行效率。緩存函數(shù)可以將輸入?yún)?shù)與其對應的結果保存在內(nèi)部,避免重復計算

function createCache() {
  var cache = {};
  return function (key, val) {
    if (!cache[key]) {
      cache[key] = val;
      console.log("保存");
    }
    return cache[key];
  };
}

var cacheModule = createCache();
cacheModule("num1", "123"); // 保存
cacheModule("num2", "456"); // 保存
cacheModule("num1", "123");
cacheModule("num2", "456");

ES6的作用域

在ES6以后引入了const、let和箭頭函數(shù),這三者對作用域分別有什么影響呢?

const、let

塊級作用域

上面說到const、let的出現(xiàn)奠定了JS中的塊級作用域的概念,使if、for等語句中也存在作用域這一功能;然而不僅僅是條件語句、循環(huán)語句,使用{...}定義的范圍都是塊級作用域,這意味著在塊級作用域內(nèi)部聲明的變量只在該作用域內(nèi)有效,并且在作用域外部無法訪問

{
  let msg = "hello";
  console.log(msg); // hello
}
console.log(msg); // msg is not defined

變量提升

使用let和const聲明的變量不會被提升到作用域的頂部,它們只能在聲明后才能被訪問;這點與var不太一樣

暫時性死區(qū)

暫時性死區(qū)指的是在變量聲明前訪問變量會拋出錯誤。只有在變量聲明語句執(zhí)行完成之后,變量才會進入有效狀態(tài),才能被訪問和使用。這點效果與上面的變量提升效果一樣

不可重復聲明

在同一個作用域中不能被重復聲明,否則會報錯;而使用var定義變量時后聲明的會覆蓋先聲明的

這三個特點可以參考下面的代碼:

console.log(var1); // 在賦值前使用了變量“var1”
const var1 = 11;
let var2 = 22; // 無法重新聲明塊范圍變量“var2”
let var2 = 22;

箭頭函數(shù)

箭頭函數(shù)在JavaScript中仍然與普通函數(shù)一樣有函數(shù)作用域的概念

題外話

動態(tài)作用域與詞法作用域

作用域的種類有兩種:分別是動態(tài)作用域和詞法作用域(靜態(tài)作用域)。上述我們介紹的是詞法作用域,什么是詞法作用域?

詞法作用域

詞法作用域是基于代碼的靜態(tài)結構來確定變量的訪問規(guī)則。也就是說它由變量和函數(shù)在代碼中的聲明位置而不是調用的位置來確定,思考下面的代碼

function foo1() {
  var var1 = 10; // foo2可訪問的作用域
  // 聲明foo2的作用域
  return function foo2() {
    console.log(var1);// 10
  };
}
var foo2 = foo1();
function foo3() {
  var var1 = 20; // foo2不可訪問的作用域
  // 執(zhí)行foo2的作用域
  foo2();
}
foo3();

在foo1中聲明了函數(shù)foo2,在foo3中執(zhí)行foo2,可以看到,foo2取的var1是聲明foo2的作用域中的變量(10)。這個現(xiàn)象說明JS采用的是詞法作用域。

動態(tài)作用域

那么反之,如果還是上述代碼,foo2取的var1是執(zhí)行foo2的作用域中的變量(20),就說明語言采用的是動態(tài)作用域

總結

JavaScript作用域與變量提升是編寫高質量代碼所必須掌握的重要概念。本文介紹了作用域的定義、作用和目的,以及JavaScript中的不同作用域類型,包括全局作用域、函數(shù)作用域和塊級作用域。我們還討論了變量提升的概念、原理和影響范圍,以及作用域鏈和閉包的關系。此外,還探討了ES6的作用域,并對比了其與早期作用域的區(qū)別。最后針對動態(tài)作用域與詞法作用域作了一個簡單的說明。

好了,以上就是文章的全部內(nèi)容了,謝謝你看到了這里,如果覺得文章不錯的話,還望三連支持一下,感謝支持!文章來源地址http://www.zghlxwxcb.cn/news/detail-679927.html

到了這里,關于JavaScript作用域詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 學習Node.js需要哪些JavaScript知識

    Lexical Structure ( 詞法 ) JavaScript 的詞法(lexical grammar)。ECMAScript 源碼文本會被從左到右掃描 ,并被轉換為一系列的輸入元素,包括 token、控制符、行終止符、注釋和空白符。ECMAScript 定義了一些、字面量以及行尾分號補全的規(guī)則。 Expressions ( 表達式 ) JavaScript 中的

    2024年02月03日
    瀏覽(13)
  • 運行 Node.js 與瀏覽器 JavaScript

    瀏覽器和 Node.js 都使用 JavaScript 軟件語言 - 但字面上的 運行時環(huán)境 是不同的。 Node.js(又名服務器端 JavaScript)與客戶端 JavaScript 有許多相似之處。它也有很多差異。 盡管兩者都使用 JavaScript 作為軟件語言,但我們可以重點關注一些關鍵差異,這些差異使兩者之間的軟件開發(fā)

    2024年02月09日
    瀏覽(29)
  • 前后端交互系統(tǒng):在Node.js中運行JavaScript

    前后端交互系統(tǒng):在Node.js中運行JavaScript

    在Node.js中運行JavaScript,您需要編寫適用于服務器端的代碼,而不是瀏覽器端的代碼。以下是一些示例代碼,用于在Node.js中創(chuàng)建一個簡單的HTTP服務器并在瀏覽器中訪問它: 將上述代碼保存到一個名為main.js的文件中,然后在命令行中運行 node .main.js。這將創(chuàng)建一個簡單的HTT

    2024年02月08日
    瀏覽(29)
  • 【34JavaScript let 和 const】JavaScript中的“l(fā)et“和“const“關鍵字詳解:作用、用法及區(qū)別

    // 使用 let 聲明變量 let x = 10; // 在同一作用域內(nèi)重新賦值 x = 20; // 在不同的作用域內(nèi)使用 let 聲明變量 function example() { let y = 30; console.log(x); // 輸出:20 console.log(y); // 輸出:30 } console.log(x); // 輸出:20 console.log(y); // 報錯:y is not defined // 使用 const 聲明常量 const PI = 3.14159; // 嘗

    2024年02月08日
    瀏覽(24)
  • 將 Jupyter Notebook 用于 JavaScript (使用 Node.js 或 Deno 環(huán)境)

    熟悉 Python 的讀者, 可能同樣對 IPython 或 Jupyter 等項目 (如 Jupyter Notebook) 有所耳聞. 正如其名, IPython 項目讓 Python 這門語言變得 “interactive”; 如: 交互式的 Shell 程序, 對交互式數(shù)據(jù)可視化以及 GUI 工具集的支持等等 (具體可見 IPython 項目的網(wǎng)站). 比如在 Notebook 中, 用戶可以實現(xiàn)

    2024年02月07日
    瀏覽(19)
  • Node.js安裝與配置指南:輕松啟航您的JavaScript服務器之旅

    Node.js作為一個基于Chrome V8引擎的JavaScript運行時環(huán)境,已經(jīng)成為現(xiàn)代web開發(fā)中不可或缺的重要工具之一。它的出現(xiàn)極大地擴展了JavaScript的應用范圍,使得開發(fā)者可以利用同一種語言來編寫前端和后端的代碼,從而實現(xiàn)全棧開發(fā)。Node.js具有非阻塞I/O、事件驅動的特性,使得它能

    2024年04月10日
    瀏覽(25)
  • 2023年最佳JavaScript框架:React、Vue、Angular和Node.js的比較

    2023年最佳JavaScript框架:React、Vue、Angular和Node.js的比較

    ??歡迎來到Java學習路線專欄~探索2023年最佳JavaScript框架:React、Vue、Angular和Node.js的比較 ☆* o(≧▽≦)o *☆嗨~我是IT·陳寒?? ?博客主頁:IT·陳寒的博客 ??該系列文章專欄:Java學習路線 ??其他專欄:Java學習路線 Java面試技巧 Java實戰(zhàn)項目 AIGC人工智能 ??文章作者技術和水

    2024年02月11日
    瀏覽(29)
  • Node.js和瀏覽器在JavaScript運行環(huán)境方面存在一些區(qū)別和聯(lián)系

    Node.js和瀏覽器在JavaScript運行環(huán)境方面確實存在一些區(qū)別和聯(lián)系。 首先,讓我們理解一下Node.js和瀏覽器的運行環(huán)境。Node.js是一個基于Chrome的V8引擎的服務器端JavaScript運行環(huán)境,允許開發(fā)者在服務器端運行JavaScript代碼,并且提供了一系列的內(nèi)置模塊,如fs模塊用于文件系統(tǒng)操

    2024年03月14日
    瀏覽(30)
  • 【面試題】詳解JavaScript中的Map()

    ?前端面試題庫 ( 面試必備) ?? ? ? ? ? ? 推薦:★★★★★ 地址:前端面試題庫 JavaScript是一種動態(tài)、解釋性的編程語言,用于開發(fā)web上的動態(tài)頁面和交互式應用程序。與其他編程語言相比,JavaScript擁有更加靈活的內(nèi)置數(shù)據(jù)類型,并且擁有更高級別的調試和錯誤處理工

    2024年02月11日
    瀏覽(25)
  • 完成一個有趣的Web期末大作業(yè)(html、css、javascript、MySQL、Node.js)

    完成一個有趣的Web期末大作業(yè)(html、css、javascript、MySQL、Node.js)

    題目:學校老師的要求很開放,要自己做一個感興趣的網(wǎng)頁,要求使用基礎的html、css和javascript,后端要使用數(shù)據(jù)庫。 網(wǎng)上都是各種管理系統(tǒng),看多了覺得沒啥意思,要做一個自己感興趣的網(wǎng)站。近幾年沉迷犬夜叉這部動漫,就花了兩天的時間創(chuàng)建了一個犬夜叉的網(wǎng)站,對于

    2024年02月04日
    瀏覽(28)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包