成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

JS進(jìn)擊之路:作用域

el09xccxy / 622人閱讀

摘要:如果是,編譯器會(huì)忽略該聲明,繼續(xù)進(jìn)行編譯否則它會(huì)要求作用域在當(dāng)前作用域的集合中聲明一個(gè)新的變量接下來編譯器會(huì)為引擎生成運(yùn)行時(shí)所需的代碼,這些代碼被用來處理這個(gè)賦值操作。引擎運(yùn)行時(shí)會(huì)首先詢問作用域,在當(dāng)前的作用域集合中是否存在一個(gè)叫做的變量。

引言

幾乎所有的編程語言都有作用域的概念,那作用域到底指的是什么呢?作用域就是編程語言在定義變量時(shí),變量如何存儲(chǔ)、變量如何訪問的一套規(guī)則,不同的編程語言的規(guī)則大同小異,接下來就來看看這套規(guī)則是怎么設(shè)定的

編譯原理

在傳統(tǒng)編譯語言中,在代碼執(zhí)行之前都會(huì)有一個(gè)編譯過程:

分詞/詞法分析:將代碼語句分解成有意義的代碼塊,又叫詞法單元。

解析/語法分析:將詞法單元轉(zhuǎn)換一個(gè)逐級(jí)嵌套的具有語法規(guī)則的樹狀結(jié)構(gòu),又叫抽象語法樹(AST)

代碼生成:解析AST并轉(zhuǎn)化成機(jī)器指令

和傳統(tǒng)編譯語言不太一樣,js的編譯和執(zhí)行并不是分開執(zhí)行,大多數(shù)情況都是編譯過程結(jié)束就會(huì)立刻執(zhí)行,為了在短時(shí)間的編譯過程內(nèi)達(dá)到較優(yōu)性能,js引擎較一般編譯器更復(fù)雜,現(xiàn)在就讓來看js的編譯過程,簡單的以編譯var a = 2為例:

遇到var a,編譯器會(huì)詢問作用域是否已經(jīng)有一個(gè)該名稱的變量存在于同一個(gè)作用域的集合中。如果是,編譯器會(huì)忽略該聲明,繼續(xù)進(jìn)行編譯;否則它會(huì)要求作用域在當(dāng)前作用域的集合中聲明一個(gè)新的變量a

接下來編譯器會(huì)為引擎生成運(yùn)行時(shí)所需的代碼,這些代碼被用來處理a=2這個(gè)賦值操作。引擎運(yùn)行時(shí)會(huì)首先詢問作用域,在當(dāng)前的作用域集合中是否存在一個(gè)叫做a的變量。如果否,引擎就會(huì)使用這個(gè)變量;如果引擎最終找到了a,就會(huì)將2賦值給它。否則引擎就會(huì)拋出一個(gè)異常

詞法作用域

作用域一般有兩種工作模型,第一種是被大多數(shù)編程語言所采用的詞法作用域,另外一種叫作動(dòng)態(tài)作用域,如Bash腳本采用的就是動(dòng)態(tài)作用域。詞法作用域就是定義在詞法階段的作用域,詞法作用域是由你在寫代碼時(shí)將變量和塊作用域?qū)懺谀睦飦頉Q定的,由變量定義位置決定,而動(dòng)態(tài)作用域則是由變量使用的位置來決定的。下面來看個(gè)例子:

function foo(a) {
  var b = a * 2;
  function bar(c) {
    console.log(a, b, c)
  }
  bar(b * 3)
}
foo(2)

首先來分析一下這里一共存在幾個(gè)作用域?

全局作用域,里面存在foo變量

foo函數(shù)創(chuàng)建的作用域,里面有a,b,bar變量

bar函數(shù)創(chuàng)建的作用域,里面有c變量

接下來再來分析一下變量的查找過程,引擎執(zhí)行console.log()需要查找a、b、c三個(gè)變量的引用,首先從最里面的bar()作用域開始找,引擎無法找到a,因此會(huì)再往上到foo()作用域中找,在這里找到了a,停止查找,對于b、c來說查找過程一樣。作用域查找始終從運(yùn)行時(shí)最內(nèi)層開始查找,逐級(jí)向外查找,直到遇見第一個(gè)匹配的變量為止。

函數(shù)作用域

函數(shù)作用域指的是屬于這個(gè)函數(shù)的全部變量都可以在整個(gè)函數(shù)的范圍內(nèi)使用及復(fù)用,這是大家都知道的定義,但是函數(shù)作用域的存在到底有什么用呢?接下來就一起看看函數(shù)作用域的秒用。

隱藏內(nèi)部實(shí)現(xiàn)

隱藏內(nèi)部實(shí)現(xiàn)就是將變量和函數(shù)包裹在一個(gè)函數(shù)的作用域中,達(dá)到隱藏的目的,為什么要這么做呢?軟件設(shè)計(jì)中有一個(gè)非常有名的原則叫最小暴露原則,指最小限度暴露必要內(nèi)容,而將其他內(nèi)容都隱藏起來,比如模塊或?qū)ο蟮腁PI設(shè)計(jì)。用函數(shù)作用域來包裹變量和函數(shù)來達(dá)到最小暴露原則,阻止外部直接訪問,來看下面的例子:

function?doSomething(a)?{
??b?=?a?+?doSomethingElse(?a?*?2?);
??console.log(?b?*?3?);
}
  
function?doSomethingElse(a)?{
? return?a?-?1;
}
var?b;
doSomething(?2?);?//?15”

在這段代碼中doSomethingElse和b應(yīng)該是doSomething內(nèi)部私有的,但是卻被暴露出來,這樣會(huì)導(dǎo)致以預(yù)期之外的形式被使用,產(chǎn)生意料之外的結(jié)果,更合理的設(shè)計(jì)應(yīng)該是將這些私有的內(nèi)容隱藏在doSomething內(nèi)部,例如:

function?doSomething(a)?{
  function?doSomethingElse(a)?{
??  return?a?-?1;
  }
??var?b;
??b?=?a?+?doSomethingElse(?a?*?2?);
??console.log(?b?*?3?);
}
doSomething(?2?);

這樣b和doSomethingElse都無法從doSomething外部訪問,但是這樣也會(huì)存在一些問題,首先在全局作用域中聲明了doSomething函數(shù),污染了全局作用,其次,必須通過顯示調(diào)用才能執(zhí)行,那么有沒有什么辦法既不會(huì)污染作用域也不需要調(diào)用就可以自執(zhí)行呢?答案就是函數(shù)表達(dá)式,看下面的例子:

(function?doSomething(a)?{
  function?doSomethingElse(a)?{
??  return?a?-?1;
  }
??var?b;
??b?=?a?+?doSomethingElse(?a?*?2?);
??console.log(?b?*?3?);
})(2)

首先來看(function doSomething(){})這是一個(gè)函數(shù)表達(dá)式,和函數(shù)聲明不同的是用括號(hào)包起來的,然后再(function doSomething(a){})()調(diào)用傳值,這樣既能自執(zhí)行也不會(huì)污染作用域,社區(qū)給這種用法定義了一個(gè)術(shù)語:IIFE,代表立即執(zhí)行函數(shù)表達(dá)式

塊作用域

除JavaScript外很多編程語言都支持塊作用域,盡管你可能寫過很偽塊作用域形式的代碼,最常見的就是for循環(huán):

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

寫這段代碼通常是希望變量i在循環(huán)內(nèi)部使用,但是實(shí)際上i會(huì)被綁定到外部作用域中,要確保沒有在作用域的其他地方意外使用i,就只能依靠自覺,這時(shí)候塊級(jí)作用域就顯得尤為有用,ES6改變了現(xiàn)狀,引入了新的let、const關(guān)鍵字,let關(guān)鍵字可以將變量綁定到所在的任意作用域中,也就是let為其聲明的變量隱式地創(chuàng)建了作用域:

for(let i=0; i<10; i++) {
  console.log(i)        
}
console.log(i) // ReferenceError

這時(shí)候i就只會(huì)在for循環(huán)的內(nèi)部有效

總結(jié)

這篇文章主要介紹了JS作用域相關(guān)的內(nèi)容。如果有錯(cuò)誤或不嚴(yán)謹(jǐn)?shù)牡胤?,歡迎批評(píng)指正,如果喜歡,歡迎點(diǎn)贊。

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

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/109081.html

相關(guān)文章

  • JS進(jìn)擊之路:閉包

    摘要:常見問題說到閉包相關(guān)的問題,最典型的就是變量和指向這兩類問題。如果有錯(cuò)誤或不嚴(yán)謹(jǐn)?shù)牡胤?,歡迎批評(píng)指正,如果喜歡,歡迎點(diǎn)贊。 引言 閉包這個(gè)詞對很多前端開發(fā)人員來說既熟悉又陌生,熟悉是因?yàn)楹芏嗳硕加眠^閉包,但是用的時(shí)候不知道閉包,陌生是因?yàn)椴⒉焕斫忾]包,接下來這篇文章將會(huì)從多方面介紹閉包 定義 閉包是怎么定義的呢?當(dāng)函數(shù)可以記住并訪問所在的詞法作用域時(shí),就產(chǎn)生了閉包,即使函數(shù)在當(dāng)前詞法作...

    tolerious 評(píng)論0 收藏0
  • 進(jìn)擊JavaScript之(二)詞法作用作用

    摘要:一作用域域表示的就是范圍,即作用域,就是一個(gè)名字在什么地方可以使用,什么時(shí)候不能使用。概括的說作用域就是一套設(shè)計(jì)良好的規(guī)則來存儲(chǔ)變量,并且之后可以方便地找到這些變量。 一、作用域 域表示的就是范圍,即作用域,就是一個(gè)名字在什么地方可以使用,什么時(shí)候不能使用。想了解更多關(guān)于作用域的問題推薦閱讀《你不知道的JavaScript上卷》第一章(或第一部分),從編譯原理的角度說明什么是作用域。概...

    denson 評(píng)論0 收藏0
  • 進(jìn)擊JavaScript之(三)玩轉(zhuǎn)閉包

    摘要:為了更好的理解,在閱讀此文之前建議先閱讀上一篇進(jìn)擊之詞法作用域與作用域鏈?zhǔn)裁词情]包閉包的含義就是閉合,包起來,簡單的來說,就是一個(gè)具有封閉功能與包裹功能的結(jié)構(gòu)。在中函數(shù)構(gòu)成閉包。 為了更好的理解,在閱讀此文之前建議先閱讀上一篇《進(jìn)擊JavaScript之詞法作用域與作用域鏈》 1.什么是閉包 閉包的含義就是閉合,包起來,簡單的來說,就是一個(gè)具有封閉功能與包裹功能的結(jié)構(gòu)。所謂的閉包就是...

    cyixlq 評(píng)論0 收藏0
  • 進(jìn)擊JavaScript之(四)原型與原型鏈

    摘要:每一個(gè)由構(gòu)造函數(shù)創(chuàng)建的對象都會(huì)默認(rèn)的連接到該神秘對象上。在構(gòu)造方法中也具有類似的功能,因此也稱其為類實(shí)例與對象實(shí)例一般是指某一個(gè)構(gòu)造函數(shù)創(chuàng)建出來的對象,我們稱為構(gòu)造函數(shù)的實(shí)例實(shí)例就是對象。表示該原型是與什么構(gòu)造函數(shù)聯(lián)系起來的。 本文您將看到以下內(nèi)容: 傳統(tǒng)構(gòu)造函數(shù)的問題 一些相關(guān)概念 認(rèn)識(shí)原型 構(gòu)造、原型、實(shí)例三角結(jié)構(gòu)圖 對象的原型鏈 函數(shù)的構(gòu)造函數(shù)Function 一句話說明什么...

    XBaron 評(píng)論0 收藏0
  • 進(jìn)擊的 JavaScript(三) 之 函數(shù)執(zhí)行過程

    摘要:中沒有可執(zhí)行的函數(shù)了,執(zhí)行完出棧。當(dāng)某個(gè)函數(shù)被調(diào)用時(shí),會(huì)創(chuàng)建一個(gè)執(zhí)行環(huán)境及相應(yīng)的作用域鏈。檢查當(dāng)前環(huán)境中的函數(shù)聲明使用聲明的。確定指向所以說的指向,是在函數(shù)執(zhí)行時(shí)確定的。 理解js 的執(zhí)行過程是很重要的,比如,作用域,作用域鏈,變量提升,閉包啊,要想明白這些,你就得搞懂函數(shù)執(zhí)行時(shí)到底發(fā)生了什么! 一、執(zhí)行環(huán)境(Execution Context)又稱執(zhí)行上下文 當(dāng)代碼執(zhí)行時(shí)都會(huì)產(chǎn)生一個(gè)...

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

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

0條評(píng)論

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