成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript之變量及作用域

Faremax / 2629人閱讀

摘要:所以的作用域是靜態(tài)作用域,也叫詞法作用域。總結(jié)是一門基于詞法作用域靜態(tài)作用域的語(yǔ)言,會(huì)沿著作用域鏈像氣泡一樣向外部尋找變量聲明。又是函數(shù)作用域的語(yǔ)言,在中,使用和關(guān)鍵字后,能讓變量處于塊作用域中,而且不存在聲明提升。

本文共 1700 字,讀完只需 7 分鐘
概述

變量,編程語(yǔ)言中我們用來模擬現(xiàn)實(shí)概念的工具,比方說,變量可以表示對(duì)象,數(shù)組,數(shù)字,字符。既然是工具,那么就用工具的適用范圍,這個(gè)工具在這個(gè)適用范圍中才有效,在編程語(yǔ)言中,我們稱這個(gè)適用范圍叫作用域(scope)

本文會(huì)總結(jié) JS 中作用域的相關(guān)概念。

什么是作用域

全局作用域

函數(shù)作用域

塊級(jí)作用域

詞法作用域(靜態(tài)作用域)

作用域鏈

一、什么是作用域?

作用域, 英文意思是 scope, 我自己的話來理解就是:

變量訪問規(guī)則的有效范圍

作用域外,無法引用作用域內(nèi)的變量

離開作用域后,作用域的變量的內(nèi)存空間會(huì)被清除,比如執(zhí)行完函數(shù)或者關(guān)閉瀏覽器。

二、全局作用域

先看一段代碼:

foo = "bar";
console.log(window.foo);  // bar

在瀏覽器環(huán)境中聲明變量,該變量會(huì)默認(rèn)成為全局 windows 對(duì)象的屬性。

再看下面這段代碼:

function foo() {
    name = "bar"
}
foo();
console.log(window.name) // bar

在函數(shù)中,如果不加 bar聲明一個(gè)變量,那么這個(gè)變量會(huì)默認(rèn)被聲明為全局變量,如果是嚴(yán)格模式則會(huì)報(bào)錯(cuò)。

全局變量可以在任何地方訪問到,但是有很大的問題存在。

全局變量會(huì)造成命名污染,如果在多處對(duì)同一個(gè)全局變量進(jìn)行操作,那么就會(huì)覆蓋全局變量的定義。同時(shí)全局變量數(shù)量過多,非常不方便管理。

這也是為什么像jQuery 和 underscore 這樣的類庫(kù),要在全局建立 $ 和 _ 變量,其余私有方法屬性掛載到該全局變量下。

三、函數(shù)作用域

JS 是函數(shù)作用域,在函數(shù)中定義一個(gè)局部變量,那么該變量只可以在該函數(shù)作用域中被訪問。

function doSomething() {
    var thing = "吃早餐";
}

console.log(thing);  // Uncaught ReferenceError: thing is not defined

嵌套函數(shù)作用域:

function outter() {
    var thing = "吃早餐";
    function inner() {
        console.log(thing);
    }
    inner();
}

outter();  // 吃早餐

在外層函數(shù)中,嵌套一個(gè)內(nèi)層函數(shù),那么這個(gè)內(nèi)層函數(shù)可以向上訪問到外部作用域的變量。

那么,既然內(nèi)層函數(shù)可以訪問到外層函數(shù)的變量,那么把內(nèi)層函數(shù)返回后呢?

function outter() {
    var thing = "吃晚餐";
    
    function inner() {
        console.log(thing);
    }
    return inner;
}

var foo = outter();
foo();  // 吃晚餐

前面我們提到了,函數(shù)執(zhí)行完后,函數(shù)作用域的變量會(huì)被垃圾回收,以上代碼可以看出當(dāng)我們返回了一個(gè)訪問了外部函數(shù)變量的內(nèi)部函數(shù),最后外部函數(shù)的變量得以保存。

這種當(dāng)變量存在的函數(shù)已經(jīng)執(zhí)行結(jié)束,但仍在可以訪問的方式就是`閉包`。

閉包的具體實(shí)踐,后續(xù)文章會(huì)詳細(xì)說明。
四、塊級(jí)作用域

JS 在 ES6 之前只有函數(shù)作用域,沒有塊級(jí)作用域的概念。
看一下代碼:

function doSomething() {
    for (var i = 0; i < 10; i++) {
        ...
    }
    console.log(i)
}
doSomething();  // 10

由于 JS 沒有塊級(jí)作用域,變量 i 在函數(shù)作用域中只有一個(gè),每次 for 循壞都在改變這一個(gè)變量。

再看阮一峰老師 ES6 教程里的一段代碼:

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6]();   // 10;

以上代碼中,由于沒有塊級(jí)作用域,i 變量全局只有一個(gè),當(dāng) for 循壞結(jié)束,變量 i 的值等于 10, 所以 a[6]() 對(duì)應(yīng)函數(shù)內(nèi)的變量 i 的打印值就是 10。

ES 6 中通過 letconst關(guān)鍵字 引用了塊級(jí)作用域的概念,所謂塊級(jí)作用域,就是以 {}包裹的區(qū)域。

我們將阮一峰老師 ES6 教程里的一段代碼改成 let 的形式:

var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6]();   // 6;

這時(shí),數(shù)組內(nèi)的索引為6函數(shù)內(nèi)的變量打印值為6,每次循環(huán),會(huì)創(chuàng)建新的塊級(jí)作用域,然后重新聲明一個(gè)新的變量 i;JS 的解釋引擎會(huì)記住上次循環(huán)的變量值,所以能夠返回正確的結(jié)果。

letconst 會(huì)聲明一個(gè)塊級(jí)作用域的變量及常量,不易發(fā)生變量命名污染的問題,能規(guī)避沖突,幫助你寫出簡(jiǎn)潔優(yōu)雅的代碼,建議一直使用。

五、詞法作用域(靜態(tài)作用域)

詞法作用域,也可以叫做靜態(tài)作用域,是什么意思呢?

無論函數(shù)在哪里調(diào)用,詞法作用域都只由函數(shù)被聲明時(shí)所處的位置決定。

既然有靜態(tài)作用域,那么也有動(dòng)態(tài)作用域。

而動(dòng)態(tài)作用域的作用域則是由函數(shù)被調(diào)用執(zhí)行的位置所決定。

var a = 123;

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

function func2() {
    var a = 456;
    func1();
}

func2(); // 123

以上代碼,最后輸出結(jié)果 a 的值,來自于 func1 聲明時(shí)所在位置訪問到的 a 值 123。

所以 JS 的作用域是靜態(tài)作用域,也叫詞法作用域。

六、作用域鏈

在 JS 引擎中,通過標(biāo)識(shí)符查找標(biāo)識(shí)符的值,會(huì)從當(dāng)前作用域向上尋找,直到作用域找到第一個(gè)匹配的標(biāo)識(shí)符為止。就是 JS 的作用域鏈

如果嵌套作用域有多個(gè)相同標(biāo)識(shí)符,那么,最內(nèi)部的標(biāo)識(shí)符會(huì)覆蓋外層標(biāo)識(shí)符,這叫做“遮蔽效應(yīng)”

var a = 1;
function func1() {
    var a = 2;
    function func2() {
        var a = 3;
        console.log(a);  // 3
    }
    func2();
}

func1(); // 3

func2 中變量 a,會(huì)從內(nèi)部開始向外部上層尋找,找到最近的 a 標(biāo)識(shí)符的聲明為止。

總結(jié)

JS 是一門基于詞法作用域(靜態(tài)作用域)的語(yǔ)言,JS 會(huì)沿著作用域鏈像氣泡一樣向外部尋找變量聲明。

JS 又是函數(shù)作用域的語(yǔ)言,在 ES6 中,使用 letconst 關(guān)鍵字后,能讓變量處于塊作用域中,而且不存在聲明提升。

后面的文章會(huì)介紹 JS 中的聲明提升和閉包,敬請(qǐng)期待。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/98330.html

相關(guān)文章

  • javascript作用和閉包我見

    摘要:查詢是在作用域鏈中,一級(jí)級(jí)的往上查找該變量的引用。作用域和作用域鏈作用域的概念,應(yīng)該兩張圖幾句話就能解釋吧。這個(gè)建筑代表程序中的嵌套作用域鏈。一層嵌一層的作用域形成了作用域鏈,變量在作用域鏈中的函數(shù)內(nèi)得到了自己的定義。 javascript作用域和閉包之我見 看了《你不知道的JavaScript(上卷)》的第一部分——作用域和閉包,感受頗深,遂寫一篇讀書筆記加深印象。路過的大牛歡迎指點(diǎn)...

    SoapEye 評(píng)論0 收藏0
  • JS編譯 LHS RHS(你不知道的JavaScript 小記一)

    摘要:關(guān)于兩個(gè)專業(yè)術(shù)語(yǔ)的討論起自對(duì)你不知道的一書的閱讀學(xué)習(xí)。遇到,編譯器會(huì)詢問作用域是否已經(jīng)有一個(gè)該名稱的變量存在于同一個(gè)作用域的集合中。摘錄來自你不知道的。 JS 編譯之 LHS RHS 一、前言 最近和朋友聊技術(shù)的時(shí)候,聊到 LHS RHS,我竟然沒聽說過 沒聽說過。。。 于是成功引起了我的好奇心。 關(guān)于兩個(gè)專業(yè)術(shù)語(yǔ)的討論起自對(duì)《你不知道的JavaScript》一書的閱讀學(xué)習(xí)。 二、編譯...

    Cristic 評(píng)論0 收藏0
  • JavaScript 闖關(guān)記

    摘要:對(duì)象數(shù)組初始化表達(dá)式,闖關(guān)記之上文檔對(duì)象模型是針對(duì)和文檔的一個(gè)。闖關(guān)記之?dāng)?shù)組數(shù)組是值的有序集合。數(shù)組是動(dòng)態(tài)的,根闖關(guān)記之語(yǔ)法的語(yǔ)法大量借鑒了及其他類語(yǔ)言如和的語(yǔ)法。 《JavaScript 闖關(guān)記》之 DOM(下) Element 類型 除了 Document 類型之外,Element 類型就要算是 Web 編程中最常用的類型了。Element 類型用于表現(xiàn) XML 或 HTML 元素...

    mj 評(píng)論0 收藏0
  • 前端面試閉包

    摘要:在函數(shù)內(nèi)部的變量稱之為局部變量,它可以在函數(shù)內(nèi)部讀取,在函數(shù)外部無法正常讀取,如果想要讀取函數(shù)內(nèi)部的變量則需要用到閉包。 前端面試之閉包 閉包屬于屬于JavaScript的難點(diǎn),但是在很多高級(jí)應(yīng)用都需要用到,也是前端面試中經(jīng)常會(huì)考到的點(diǎn)。 作用域 談到閉包首先必須了解作用域,ES5中,JavaScript的作用域只有兩種,一種是全局作用域,變量在整個(gè)程序中一直存在,所有地方都可以讀??;...

    jackzou 評(píng)論0 收藏0
  • Javascript重溫OOP作用與閉包

    摘要:的變量作用域是基于其特有的作用域鏈的。需要注意的是,用創(chuàng)建的函數(shù),其作用域指向全局作用域。所以,有另一種說法認(rèn)為閉包是由函數(shù)和與其相關(guān)的引用環(huán)境組合而成的實(shí)體。 作用域 定義 在編程語(yǔ)言中,作用域控制著變量與參數(shù)的可見性及生命周期,它能減少名稱沖突,而且提供了自動(dòng)內(nèi)存管理 --javascript 語(yǔ)言精粹 我理解的是,一個(gè)變量、函數(shù)或者成員可以在代碼中訪問到的范圍。 js的變量作...

    JessYanCoding 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<