JavaScript 1、 ES6 聲明變量,做用域理解

// JavaScript
/*
* =========================================================
*
* 編譯原理
* 儘管一般將 JavaScript 歸類爲「動態」或「解釋執行」語言,但事實上它是一門編譯語言。 這個事實對你來講可能顯而易見,也可能你聞所未聞,取決於
* 你接觸過多少編程語言,具備多少經驗。但與傳統的編譯語言不一樣,它不是提早編譯的,編譯結果也不能在分佈式系 統中進行移植。
*
* 分詞/詞法分析(Tokenizing/Lexing)
* 這個過程會將由字符組成的字符串分解成(對編程語言來講)有意義的代碼塊,這些代 碼塊被稱爲詞法單元(token)。
* 例如,考慮程序var a = 2;。這段程序一般會被分解成 爲下面這些詞法單元:var、a、=、2 、;。空格是否會被看成詞法單元,取決於空格在
* 這門語言中是否具備意義。
*
*
* 解析/語法分析(Parsing)
* 這個過程是將詞法單元流(數組)轉換成一個由元素逐級嵌套所組成的表明了程序語法 結構的樹。這個樹被稱爲「抽象語法樹」
* (Abstract Syntax Tree,AST)。 var a = 2; 的抽象語法樹中可能會有一個叫做 VariableDeclaration 的頂級節點,接下 來是一個叫做
* Identifier(它的值是 a)的子節點,以及一個叫做 AssignmentExpression 的子節點。AssignmentExpression 節點有一個叫做
* NumericLiteral(它的值是 2)的子 節點。
*
* 代碼生成
* 將 AST 轉換爲可執行代碼的過程稱被稱爲代碼生成。這個過程與語言、目標平臺等息 息相關。 拋開具體細節,簡單來講就是有某種方法能夠
* 將 var a = 2; 的 AST 轉化爲一組機器指 令,用來建立一個叫做 a 的變量(包括分配內存等),並將一個值儲存在 a 中。 * * * * JavaScript 三大實現構成 * 1、ECMAScript:JavaScript的核心 * 2、DOM(document object model):把整個頁面映射爲一個多節點的結構,藉助DOM提供的API,能夠輕鬆的對節點增長,刪除,替換。 * 3、BOM(browser object model):能夠控制瀏覽器顯示的頁面之外的東西,如:窗口和框架等。 * * WEB瀏覽器只是ECMAScript的宿主環境之一,其次還有:Node,Adobe Flash等。 * * JavaScript 中頂層對象 * 一、window對象,它是JavaScript的最頂層對象,其它的BOM對象都是windows對象的屬性; * 二、document對象表示瀏覽器中加載頁面的文檔對象; * 三、location對象包含了瀏覽器當前的URL信息; * 四、navigator對象包含了瀏覽器自己的信息; * 五、screen對象包含了客戶端屏幕及渲染能力的信息; * 六、history對象包含了瀏覽器訪問網頁的歷史信息。 * * 變量:聲明的變量是存在與棧內存(先進後出),引用存放在堆內存(先進先出),。 * 1.棧內存:存儲變量,包括引用變量,存儲在RAM中,是先進後出的,而且像列表同樣的由上而下排列,向下則是增長一個變量,向上則是釋放一個變量。 * 2.堆內存:存儲對象,存儲在RAM中,是先進先出,像集合同樣的一個內存池。 * * 做用域:定義存儲變量的一套規則,LHS(爲變量賦值) 和 RHS(獲得某某的值),並在的編譯時,編譯器和引擎都須要和做用域 * 一次次的溝通並確認做用域中是否存在此變量。 * * 當一個html文件調用多個js文件時(只有一個窗口),使用var定義變量時:它們都屬於同一個做用域,而且window這種頂層對象中時共用的。 * * 當使用LET定義變量時,不會出如今頂層對象(window)中,ES6引入了塊的概念,因此let定義的變量時存儲在當前塊(暫存死區)中,在此塊以外的地方 * 都將不能使用,而且在let以前使用let定義的變量將直接拋出 ReferenceError錯誤。 * * var定義的變量將出如今頂層對象(window)中,var定義變量時,會有一個變量提高的功效:即的var定義變量以前可使用,但值卻時undefined,由於 * 在編譯的過程當中會把變量聲明提高到當前做用域的最上方,即:var a = 10; 在編譯時,var a; 而後是 a = 10;變量賦值並無作提高,只是聲明被提高了, * 這是由於:JavaScript 在語言設計時,易與實現。 * * const定義的值變量,並不能更改其值。當定義引用變量時,其值是能夠更換的,可是引用是不能更換,不然都將拋出TypeError * * *不使用標示符聲明變量* * 不使用標示符聲明變量,相似var聲明變量同樣,有一個特性不一樣,在非嚴格模式下,當在做用域對變量進行RHS(獲得某某的值),若是直至全局做用域找不到, * 將會拋出ReferenceError,若是在做用域對變量進行LHS(爲某某變量賦值),直至全局做用域還找不到變量,全局做用域中就會"建立一個"具備該名稱的 * 全局變量並將其返還給引擎。 * * *嚴格模式* * 與鬆散模式相比,其中一個不一樣的行爲是嚴格模式禁止自動或隱式地建立全局變量,LHS查詢失敗時,會與RHS同樣拋出ReferenceError。 * * Error * ReferenceError 同做用域判別失敗相關,而 TypeError 則表明做用域判別成功了,可是對 結果的操做是非法或不合理的。 * * 函數:定義函數分爲兩種,1.function a(){}, 2.var a = function(){},前者是'函數聲明',後者是'函數表達式' * 1.函數聲明會有"提高"的功效,函數表達式則"沒有提高"的功效。 * 2.函數聲明的"提高"功效,要優先與變量的提高,即:在同一個做用域中,函數聲明提高優先級大於變量優先級。 * 推薦使用1聲明函數,在ES6的出現,可使用 async 定義函數,也是推薦使用這種。 * * * * ========================================================= * */// let 定義的值不會在javascript頂層出現,只出如今當前做用域中let a = 20;console.log(this.a,'this.a'); // undefined// var 定義的變量會在頂層出現。var b = 30;console.log(this.b,'this.b'); // 30// 定義的值不會在javascript頂層出現,只出如今當前做用域中const c = 10;console.log(this.c,'this.c'); // undefined// c = 50; // 使用const定義值類型變量時,修改值內容,拋出typeErrorconst d = {a: 1, b: 2};const e = {c: 1};// d = e; // 使用const定義引用類型變量時,修改引用地址,拋出typeErrord.c = 19; // 使用const定義引用類型變量時,能夠修改引用對象內容。console.log(d, 'd object'); // 驗證經過 Object {a: 1, b: 2, c: 19} "d object"/* * ========================================================= * * JavaScript 做用域嵌套 * 1.查找變量規則 * 引擎從當前做用域中開始查找變量,若是找不到,就向上一級繼續查找,當抵達最外層的全局做用域時,不管找到仍是沒找到,查找過程都將中止。 * * 2.做用域鏈 * 做用域鏈查找變量的規則和做用域嵌套查找變量的方式是同樣的。 * * ========================================================= * */// 在foo函數中,找不到f變量時,就會向上級查找變量,在全局做用域中查找到f變量。// function foo(a) {// console.log(a + f,'==a + f');// }// var f = 2;// foo(2);// 對f RHS操做,因此會拋出ReferenceError// function foo(a) {// console.log(a + f, '==a + f');// f = a;// }// foo(2);// 非嚴格模式下,不使用var let const 等聲明變量,對l LHS操做,全局做用域中會對l,建立一個l全局變量變量。// 使用嚴格模式可驗證這個證實function foo(a) { // 'use strict'; l = a; console.log(a + l,'a+b');}foo(2);console.log(this.l,'this.l');
相關文章
相關標籤/搜索