摘要:編譯器對賦值的操作當編譯器遇到它會詢問域是否存在變量,如果存在編譯器忽略這個聲明,如果不存在編譯器要求域聲明一個新變量給自己。兩種引用引用和引用,對于編譯器來說,指變量用于賦值,是指變量用于取值。里面的也是引用,因為它用于獲取的值。
You-Dont-Know-JS是github上一個擁有9000多枚星星的JS教學文檔,評價很高,為了避免和其他翻譯文一樣,容易陷入不宜讀的混亂,也試圖避免原文中過多數(shù)的術(shù)語導致我露怯,我只提取提取我理解的一些點,通俗的講出來。今天先從第一章作用域開始吧:
原文
我的翻譯folk,希望有識之士能跟我共同完成
js和傳統(tǒng)語言一樣,也需要編譯執(zhí)行,編譯的過程通常分三步:
標記+詞法分析 Tokenizing/Lexing:: 把程序語言切成一段一段的片段,稱之為tokens。比如,程序中的 var a = 2;,會被切成如下tokens:var, a, =, 2, ;。
解析 Parsing: 把token流轉(zhuǎn)換成樹,是嵌套元素形式,符合語法結(jié)構(gòu)和規(guī)則,這個樹被稱之為"AST" (Abstract Syntax Tree).
var a = 2;的樹,開始于頂層節(jié)點 VariableDeclaration, 包含子節(jié)點 Identifier (值 a), 另外一個子節(jié)點 AssignmentExpression 包含另外子節(jié)點 NumericLiteral (值 2).
代碼生成 Code-Generation: 這個過程是把AST轉(zhuǎn)換成可執(zhí)行代碼, 這部分各程序語言和個平臺之間會有極大的不同。 所以,刨除細節(jié),var a = 2;會被轉(zhuǎn)換成機器語言,在內(nèi)存中創(chuàng)建一個變量 a,而后把值儲存其中。
編譯器對賦值的操作當編譯器遇到var a,它會詢問域是否存在變量a,如果存在編譯器忽略這個聲明,如果不存在編譯器要求域聲明一個新變量a給自己。
編譯器而后為引擎產(chǎn)生可執(zhí)行代碼,處理a = 2, 引擎首先詢問域是否有這個變量,如果沒有執(zhí)行其他操作。
兩種引用LHS(Left-hand Side)引用和 RHS(Right-hand Side)引用,對于編譯器來說,LHS指變量用于賦值,RHS是指變量用于取值。
function foo(a) { console.log( a ); // 2 } foo( 2 );
這里,foo(), 引用(變量)foo是RHS引用,因為它是用于取值的操作(將函數(shù)foo的值取出來),參數(shù)a被隱含賦值2,a = 2這里的引用a是LHS引用,因為它用于賦值。console.log(a)里面的a也是LHS引用,因為它用于獲取a的值。
這里說明的是, 代碼里的變量, 對于編譯器來說有兩種類型,用于獲取它值的是一種,本身是用于被賦值的是另外一種。
嵌套域 (Nested Scope)嵌套域很好理解,如下代碼
function foo(a) { console.log( a + b ); } var b = 2; foo( 2 ); // 4
foo函數(shù)域中沒有變量b,當引用b被調(diào)用的時候,程序會逐級往上查找,直到找到變量b,最頂層為全局變量 (global scope),如下圖所示:
錯誤但是各位有沒有想過一個問題,被賦值的引用(LHS)如果本域內(nèi)不存在會產(chǎn)生什么情況?當然,大多數(shù)人都經(jīng)歷過ReferenceError,引用錯誤。
當LHS引用(賦值引用)在域中找不到的時候,js引擎會直接拋出錯誤,而RHS引用(調(diào)用引用)如果在域中找不到的時候,js引擎會向上一級域中查找,如果依然沒有,會直接在全局域中為你自動創(chuàng)建一個(非嚴格模式下, 嚴格模式下也會報ReferenceError錯誤)。
考慮從如下代碼:
function foo(a) { console.log( a + b ); } foo( 2 );
這里的變量b因為在函數(shù)域中未定義,所以會報錯
function foo(a) { b = a; } foo( 2 );
這里的變量b也未定義,但是由于是復制操作,系統(tǒng)會為你在外層全局域里自動創(chuàng)建一個。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/91466.html
摘要:原文原文原文詞法作用域作用域有兩種常見的模型,一種叫做詞法作用域,一種叫做動態(tài)作用域。其中詞法作用域更常見,被大多數(shù)語言采用,包括。值得注意的是,一個函數(shù)作用域只有可能存在于一個父級作用域中,不會同時存在兩個父級作用域。 原文: 原文1 | 原文2 Lexical Scope - 詞法作用域 作用域有兩種常見的模型,一種叫做 詞法作用域 Lexical Scope,一種叫做...
摘要:完美的閉包,對,閉包就這么簡單。這僅僅是閉包的一部分,閉包利用函數(shù)作用域達到了訪問外層變量的目的。此時一個完整的閉包實現(xiàn)了,的垃圾回收機制由于閉包的存在無法銷毀變量。 1.閉包是指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù)。 上面這段話來自 javascript 高級程序設計 第三版 P178 。作者說閉包是一個函數(shù),它有訪問另一個函數(shù)作用域中的變量的能力。 2.函數(shù)訪問它被創(chuàng)建時所處的...
摘要:為此決定自研一個富文本編輯器。例如當要轉(zhuǎn)化的對象有環(huán)存在時子節(jié)點屬性賦值了父節(jié)點的引用,為了關于函數(shù)式編程的思考作者李英杰,美團金融前端團隊成員。只有正確使用作用域,才能使用優(yōu)秀的設計模式,幫助你規(guī)避副作用。 JavaScript 專題之惰性函數(shù) JavaScript 專題系列第十五篇,講解惰性函數(shù) 需求 我們現(xiàn)在需要寫一個 foo 函數(shù),這個函數(shù)返回首次調(diào)用時的 Date 對象,注意...
摘要:考慮這個問題還需要了解一個概念調(diào)用棧到達當前執(zhí)行位置而被調(diào)用的所有方法的堆棧。之后只要調(diào)用函數(shù),就會調(diào)用函數(shù),綁定的值始終不變。就是中新增的函數(shù)箭頭函數(shù)。 在之前的對象原型的文章中,我們講到了在函數(shù)前面加new然后進行調(diào)用之后發(fā)生的4件事情,當時只把跟原型有關的東西介紹了一下?,F(xiàn)在我們來學習一下其他的內(nèi)容。 首先先來回顧一下會有哪四件事情發(fā)生吧: 一個全新的對象被創(chuàng)建 這個新的對象會...
摘要:最近在一個前端學習群里,有人拋出了這么一道面試題。以下表示形式的是函數(shù)表達式,有多種形式。函數(shù)聲明式的函數(shù)名是可修改的。重新聲明變量通過上面的分析解釋,希望你可以掌握這道面試題,舉一反三。原文鏈接理解一道面試題 最近在一個前端學習群里,有人拋出了這么一道 JS 面試題。 var foo = 1; (function foo(){ foo = 100; console.l...
閱讀 787·2023-04-25 22:50
閱讀 1625·2021-10-08 10:05
閱讀 1062·2021-09-30 09:47
閱讀 2017·2021-09-28 09:35
閱讀 896·2021-09-26 09:55
閱讀 3493·2021-09-10 10:51
閱讀 3491·2021-09-02 15:15
閱讀 3359·2021-08-05 09:57