摘要:全局作用域局部作用域局部作用域全局作用域局部作用域塊語句沒有塊級作用域塊級聲明包括和,以及和循環(huán),和函數(shù)不同,它們不會創(chuàng)建新的作用域。局部作用域只在該函數(shù)調(diào)用執(zhí)行期間存在。
一、什么是作用域?
作用域是你的代碼在運行時,各個變量、函數(shù)和對象的可訪問性。(可產(chǎn)生作用的區(qū)域)二、JavaScript中的作用域
在 JavaScript 中有兩種作用域
全局作用域
局部作用域
當(dāng)變量定義在一個函數(shù)中時,變量就在局部作用域中,而定義在函數(shù)之外的變量則從屬于全局作用域。每個函數(shù)在調(diào)用的時候會創(chuàng)建一個新的作用域。
1.全局作用域當(dāng)你在文檔中(document)編寫 JavaScript 時,你就已經(jīng)在全局作用域中了。JavaScript
文檔中(document)只有一個全局作用域。定義在函數(shù)之外的變量會被保存在全局作用域中。
// 作用域默認(rèn)為全局作用域 var name = "andy";
全局作用域里的變量能夠在其他作用域中被訪問和修改。
var name = "andy"; console.log(name); // 輸出 "andy" function logName() { console.log(name); // "name" 變量可以在這里和其他地方訪問 } logName(); // 輸出 "andy"2.局部作用域
定義在函數(shù)中的變量就在局部作用域中。并且函數(shù)在每次調(diào)用時都有一個不同的作用域。這意味著同名變量可以用在不同的函數(shù)中。因為這些變量綁定在不同的函數(shù)中,擁有不同作用域,彼此之間不能訪問。
// 全局作用域 function someFunction() { // 局部作用域 ##1 function someOtherFunction() { // 局部作用域 ##2 } } // 全局作用域 function anotherFunction() { //局部作用域 ##3 }3.塊語句(JS沒有塊級作用域)
塊級聲明包括if和switch,以及for和while循環(huán),和函數(shù)不同,它們不會創(chuàng)建新的作用域。在塊級聲明中定義的變量從屬于該塊所在的作用域。也就是說在for、if、while等語句內(nèi)部的聲明的變量與在外部聲明是一樣的,在這些語句外部也可以訪問和修改這些變量的值。
if (true) { //這里的if條件不會創(chuàng)建一個新的作用域 var name = "Hammad"; // name 這個變量仍在全局作用域 } console.log(name); // logs "Hammad"
ECMAScript 6 引入了let和const關(guān)鍵字。這些關(guān)鍵字可以代替var。
var name = "Hammad"; let likes = "Coding"; const skills = "Javascript and PHP";
和var關(guān)鍵字不同,let和const關(guān)鍵字支持在塊級聲明中創(chuàng)建使用局部作用域。(塊級作用域)
if (true) // 這個 "if" 塊語句沒有創(chuàng)建一個塊級作用域 // name 變量處于全局作用域,因為由var關(guān)鍵字聲明 var name = "Hammad"; // likes 變量處于塊級作用域因為由let關(guān)鍵字聲明 let likes = "Coding"; // skills 變量處于塊級作用域因為由const關(guān)鍵字聲明 const skills = "JavaScript and PHP"; } console.log(name); // 輸出 "Hammad" console.log(likes); // Uncaught ReferenceError: likes is not defined console.log(skills); // Uncaught ReferenceError: skills is not defined
一個應(yīng)用中全局作用域的生存周期與該應(yīng)用相同。局部作用域只在該函數(shù)調(diào)用執(zhí)行期間存在。
4.詞法作用域所謂的 詞法( 代碼 )作用域, 就是代碼在編寫過程中體現(xiàn)出來的作用范圍. 代碼一旦寫好, 不用執(zhí)行, 作用范圍就已經(jīng)確定好了.
這個就是所謂詞法作用域.這意味著函數(shù)運行在定義它的作用域中,而不是在調(diào)用它的作用域中。
在 js 中詞法作用域規(guī)則:
函數(shù)允許訪問函數(shù)外的數(shù)據(jù).
整個代碼結(jié)構(gòu)中只有函數(shù)可以限定作用域.
作用規(guī)則首先使用提升規(guī)則分析
如果當(dāng)前作用規(guī)則中有名字了, 就不考慮外面的名字
詞法作用域var用來將變量定義在詞法作用域中(也就是function中)
function someFunc(){ var a; }
a就被函數(shù)someFunc框在了詞法作用域中
塊級作用域let和const用來將變量定義在塊級作用域中(也就是花括號中)
if(true){ let b; }
b就被if的花括號框在了塊級作用域中
5.作用域鏈可以發(fā)現(xiàn)只有函數(shù)可以制造作用域結(jié)構(gòu). 那么只要是代碼, 至少有一個作用域, 即全局作用域. 凡是代碼中有函數(shù),那么這個函數(shù)就構(gòu)成另一個作用域. 如果函數(shù)中還有函數(shù), 那么再這個作用域中就 又可以誕生一個作用域. 那么將這樣的所有的作用域列出來,可以有一個結(jié)構(gòu): 函數(shù)內(nèi)指向函數(shù)外的鏈?zhǔn)浇Y(jié)構(gòu).作用域嵌套
作用域是可以嵌套的,任務(wù)一中提到的詞法作用域和塊級作用域都可以嵌套其他作用域
(塊級作用域僅對ES6而言)
function someFunc(){ function inner(){ } }
inner就是嵌套在someFunc(詞法作用域)中的詞法作用域
if(true){ while(false){ } }
while就是嵌套在if(塊級作用域)中的塊級作用域
function someFunc(){ if(true){ } }
if就是嵌套在someFunc(詞法作用域)中的塊級作用域
作用域中的變量訪問所有的嵌套作用域都遵循以下規(guī)則:
內(nèi)部作用域有權(quán)訪問外部作用域,反之不成立。
栗子:
function someFunc(){
var outerVar = 1; function inner(){ var innerVar = 2; }
}
inner有權(quán)訪問innerVar和outerVar,但是someFunc只能訪問到outerVar
作用域是可以任意嵌套的,但是都要遵循上面的規(guī)則。
再附加一個規(guī)則:
兄弟作用域不可相互訪問
栗子:
function someFunc(){ function inner(){ } function inner2(){ } }
inner和inner2都是someFunc中的作用域,正如someFunc不能訪問inner們的作用域一樣,inner們之間也不能相互訪問。
作用域樹從上向下看這個嵌套作用域,就是棵樹!
看代碼:
function someFunc() { function inner() { } function inner2() { function foo() { } } }
看樹:
someFunc() | / / / ↓ ↓ inner() inner2() | ↓ foo()
要記住的是:inner作用域可以訪問外部作用域,但是反之不成立; foo()可以訪問inner2()中的變量,inner2()可以訪問someFunc()中的變量,這棵樹倒過來似乎更有意義,就成了鏈??!
作用域鏈從最里面看到最外面就構(gòu)成了作用域鏈
someFunc() ↑ inner2() ↑ | foo()
如果你覺得這篇文章對你有所幫助,那就順便點個贊吧,點點關(guān)注不迷路~
黑芝麻哇,白芝麻發(fā),黑芝麻白芝麻哇發(fā)哈!
前端哇發(fā)哈
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/101783.html
摘要:閉包面試題解由于作用域鏈機(jī)制的影響,閉包只能取得內(nèi)部函數(shù)的最后一個值,這引起的一個副作用就是如果內(nèi)部函數(shù)在一個循環(huán)中,那么變量的值始終為最后一個值。 (關(guān)注福利,關(guān)注本公眾號回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導(dǎo)) 本周正式開始前端進(jìn)階的第二期,本周的主題是作用域閉包,今天是第8天。 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了...
摘要:使用上一篇文章的例子來說明下自由變量進(jìn)階期深入淺出圖解作用域鏈和閉包訪問外部的今天是今天是其中既不是參數(shù),也不是局部變量,所以是自由變量。 (關(guān)注福利,關(guān)注本公眾號回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導(dǎo)) 本周正式開始前端進(jìn)階的第二期,本周的主題是作用域閉包,今天是第7天。 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了解本進(jìn)階計...
摘要:在中,通過棧的存取方式來管理執(zhí)行上下文,我們可稱其為執(zhí)行棧,或函數(shù)調(diào)用棧。因為執(zhí)行中最先進(jìn)入全局環(huán)境,所以處于棧底的永遠(yuǎn)是全局環(huán)境的執(zhí)行上下文。 一、什么是執(zhí)行上下文? 執(zhí)行上下文(Execution Context): 函數(shù)執(zhí)行前進(jìn)行的準(zhǔn)備工作(也稱執(zhí)行上下文環(huán)境) JavaScript在執(zhí)行一個代碼段之前,即解析(預(yù)處理)階段,會先進(jìn)行一些準(zhǔn)備工作,例如掃描JS中var定義的變量、...
摘要:由此可知閉包是函數(shù)的執(zhí)行環(huán)境以及執(zhí)行環(huán)境中的函數(shù)組合而構(gòu)成的。此時產(chǎn)生了閉包。二閉包的作用閉包的特點是讀取函數(shù)內(nèi)部局部變量,并將局部變量保存在內(nèi)存,延長其生命周期。三閉包的問題使用閉包會將局部變量保持在內(nèi)存中,所以會占用大量內(nèi)存,影響性能。 一、什么是閉包 1.閉包的定義 閉包是一種特殊的對象。它由兩部分構(gòu)成:函數(shù),以及創(chuàng)建該函數(shù)的環(huán)境(包含自由變量)。環(huán)境由閉包創(chuàng)建時在作用域中的任何...
摘要:本期推薦文章從作用域鏈談閉包,由于微信不能訪問外鏈,點擊閱讀原文就可以啦。推薦理由這是一篇譯文,深入淺出圖解作用域鏈,一步步深入介紹閉包。作用域鏈的頂端是全局對象,在全局環(huán)境中定義的變量就會綁定到全局對象中。 (關(guān)注福利,關(guān)注本公眾號回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導(dǎo)) 本周開始前端進(jìn)階的第二期,本周的主題是作用域閉包,今天是第6天。 本...
閱讀 4953·2023-04-25 18:47
閱讀 2684·2021-11-19 11:33
閱讀 3455·2021-11-11 16:54
閱讀 3109·2021-10-26 09:50
閱讀 2554·2021-10-14 09:43
閱讀 678·2021-09-03 10:47
閱讀 681·2019-08-30 15:54
閱讀 1508·2019-08-30 15:44