国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

理解 JavaScript 作用域

dadong / 2974人閱讀

摘要:作用域鏈前面說,作用域是根據名稱查找變量的一套規則。把這樣一層一層嵌套的作用域,叫做作用域鏈。因為這個函數名無法被外部作用域所訪問。的進階用法是給其傳入參數這樣的好處是可以縮短查詢時的作用域鏈。

上一篇文章中分析了 JS 中的數據類型和變量。這一篇文章將分析作用域,以及回答上一篇文章中變量提升的原因。

什么是作用域

作用域是一套規則,保存著變量,等待被引擎所查找。

var a = 1;
console.log(a);  // => 1
console.log(b);  // => ReferenceError

當打印 a 時,引擎就去作用域中查找 a,找到把結果返回。如果查找失敗,那么就會報錯。

詞法作用域

JS 采用的詞法作用域,也可以說是靜態作用域。簡單來說,詞法作用域是由寫代碼時將變量寫在哪里決定的。

先看一段代碼:

var a = 1;

function fn() {
    var a = 2;
    return a;
}

fn();  // => 2

當執行函數 fn 時,會返回 2,而不是 1。

作用域查找

JS 引擎會進行兩種查找,LHS 和 RHS。怎么理解?L 和 R 可以說代表左和右。什么的左和右?賦值操作的。

這里的賦值操作不一定出現 =,比如參數傳遞也是一個賦值操作。

當變量出現在賦值操作的左邊時,引擎就會對這個變量進行 LHS 查找;當出現在右邊時(這個還可以理解為取得變量的源值),就會進行 RHS 查找。

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

foo(2);

對于變量 a 來說,引擎會進行兩次查找,1 次 LHS,1 次 RHS。

調用 foo(),并傳入參數 2,這時存在著一個賦值操作即 a = 2,進行一次 LHS 查找。打印 a 時,需要獲取 a 的源值,所以進行一次 RHS 查找。

如果查詢失敗呢?

對于 LHS 來說,給未聲明的賦值就會查詢失敗。

a = 2;

但是我們知道,上面的代碼在非嚴格模式下并不會報錯,而變量 a 會被自動創建。

而對于 RHS 來說,直接使用未聲明的變量就會報 ReferenceError。

console.log(a); // => ReferenceError

另外,RHS 雖然查詢成功,但是卻對查詢結果進行非法操作,就會報 TypeError。

var foo = 1;
foo(); // => TypeError
作用域鏈

前面說,作用域是根據名稱查找變量的一套規則。而在實際情況中,經常出現多個作用域嵌套的情況。

function foo(a) {
    console.log(a + b);
}
var b = 2;
foo(2); // => 4

當引擎對 b 進行 RHS 查找時,在當前作用域無法找到,引擎就會在外層作用域中查找,直到找到這個變量,或者直到抵達最外層作用域(全局作用域)為止。

LHS 查找也是如此。

把這樣一層一層嵌套的作用域,叫做作用域鏈。

函數作用域

函數作用域是指,屬于這個函數的全部變量都可以在這個函數的范圍內使用及復用。

function foo() {
    var a = 1;
}

console.log(a); // => ReferenceError

也就是說,函數外部將無法訪問函數內部的變量。

但是這卻是非常有用的。我們可以利用函數隱藏內部實現,使其外部無法訪問、修改等。

立即執行函數表達式

利用函數作用域,可以將外部作用域無法訪問的內容包裝起來。但是,帶來了額外的一個問題,函數名本身“污染”了所在的作用域。

這時,就提出了 IIFE(立即執行函數表達式)。

(function foo() {
    // ...
}());

即包裝了內部函數,又避免了引入函數名。因為這個函數名無法被外部作用域所訪問。

IIFE 的進階用法是給其傳入參數:

(function fn(global) {
    // ...
})(window);

這樣的好處是可以縮短查詢時的作用域鏈。

塊作用域

ES6,通過 let 和 const 引入了塊作用域。

if (true) {
    let a = 1;
}
console.log(a); // => ReferenceError
變量提升

上一篇文章中中提到了變量提升。

在 JS 中,var a = 1; 這行代碼其實會被看成 var aa = 2,并在兩個階段去執行。

在編譯階段,執行聲明操作;在執行階段,執行賦值操作。

所有的變量聲明都會被提升到作用域的頂部,這個過程叫做“提升”。

函數聲明也會發生提升,并且函數聲明會先于變量提升:

var foo = 1;
function foo () {}

typeof foo; // => "number"

注意,只有函數聲明會被提升,而函數表達式不會被提升。

var foo = 1;
var foo = function () {}

typeof foo; // => "function"
小結

這篇文章梳理了 JavaScript 中作用域的基本知識。

接下來會介紹執行上下文和閉包這兩個概念,它們與作用域息息相關。

關于

這是我的公眾號,記錄著我的前端博客,沒事兒也分享一些電影、書籍。

歡迎一起交流學習。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/99470.html

相關文章

  • 深入理解JavaScript作用作用

    前言 JavaScript中有一個被稱為作用域(Scope)的特性。雖然對于許多新手開發者來說,作用域的概念并不是很容易理解,本文我會盡我所能用最簡單的方式來解釋作用域和作用域鏈,希望大家有所收獲! 想閱讀更多優質文章請猛戳GitHub博客 作用域(Scope) 1.什么是作用域 作用域是在運行時代碼中的某些特定部分中變量,函數和對象的可訪問性。換句話說,作用域決定了代碼區塊中變量和其他資源的可見...

    ytwman 評論0 收藏0
  • 深入理解JavaScript作用作用

    前言 JavaScript中有一個被稱為作用域(Scope)的特性。雖然對于許多新手開發者來說,作用域的概念并不是很容易理解,本文我會盡我所能用最簡單的方式來解釋作用域和作用域鏈,希望大家有所收獲! 想閱讀更多優質文章請猛戳GitHub博客 作用域(Scope) 1.什么是作用域 作用域是在運行時代碼中的某些特定部分中變量,函數和對象的可訪問性。換句話說,作用域決定了代碼區塊中變量和其他資源的可見...

    baiy 評論0 收藏0
  • 談談javascript語法里一些難點問題(二)

    摘要:講作用域鏈首先要從作用域講起,下面是百度百科里對作用域的定義作用域在許多程序設計語言中非常重要。原文出處談談語法里一些難點問題二 3) 作用域鏈相關的問題 作用域鏈是javascript語言里非常紅的概念,很多學習和使用javascript語言的程序員都知道作用域鏈是理解javascript里很重要的一些概念的關鍵,這些概念包括this指針,閉包等等,它非常紅的另一個重要原因就...

    Enlightenment 評論0 收藏0
  • 【譯】理解JavaScript作用

    摘要:作用域是代碼的不同部分在運行期間的可見性。大多數開發者想當然地理解作用域,但毫無疑問,有它自己的說明。變量可能是全局作用域的,或者是方法作用域的。總而言之,不要重復聲明變量,使用良好命名,盡力避免在聲明前調用和執行任何東西。 原文鏈接:https://hackernoon.com/unders... 什么是作用域? 就像JavaScript中的其他東西一樣,作用域并無特別之處。盡管大多...

    betacat 評論0 收藏0
  • Javascript】深入理解this作用問題以及new/let/var/const對this作

    摘要:理解作用域高級程序設計中有說到對象是在運行時基于函數的執行環境綁定的在全局函數中,等于,而當函數被作為某個對象調用時,等于那個對象。指向與匿名函數沒有關系如果函數獨立調用,那么該函數內部的,則指向。 理解this作用域 《javascript高級程序設計》中有說到: this對象是在運行時基于函數的執行環境綁定的:在全局函數中,this等于window,而當函數被作為某個對象調用時,t...

    snowLu 評論0 收藏0
  • 深入理解JavaScript (3) —— 作用

    摘要:針對有經驗的開發者,糾正一個過時的理解你可能聽過這句話沒有塊級作用域。詳見而且,在不使用新語法的前提下,沒有塊級作用域的正確理解應該是只有全局作用域和函數作用域。各自的作用域下,用各自的。 針對有經驗的開發者,糾正一個過時的理解:你可能聽過這句話javascript沒有塊級作用域。所謂塊,就是大括號{}中間的語句。誠然,在ES6之前,這句話是完全正確的,但ES中新增的兩個命令let和c...

    jerry 評論0 收藏0

發表評論

0條評論

dadong

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<