摘要:命令用來聲明變量,它的用法類似,但是命令聲明的變量只在所在的代碼塊中有效。不允許重復聲明不允許在同一作用域聲明兩個相同的變量。對于內部的數據結構的變化是無法控制的。
let命令
用來聲明變量,它的用法類似var,但是let命令聲明的變量只在所在的代碼塊中有效。
{ var a = 1; let b = 2; } console.log(a); // 1 console.log(b); // b is not defined b未定義
這就說明let定義的變量只在對應的代碼塊中有效。
同樣的下面是個for循環
for(let i = 0; i < 5; i++){ // ... } console.log(i);// i is not defined i未定義
i只在循環體內有效。
阮一峰老師的文章中有一個例子我們看一下并且分析一下
var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6
老師給我們的分析是這樣子的:
上面代碼中,變量i是let聲明的,當前的i只在本輪循環有效,所以每一次循環的i其實都是一個新的變量,所以最后輸出的是6。你可能會問,如果每一輪循環的變量i都是重新聲明的,那它怎么知道上一輪循環的值,從而計算出本輪循環的值?這是因為 JavaScript 引擎內部會記住上一輪循環的值,初始化本輪的變量i時,就在上一輪循環的基礎上進行計算。
如果還不理解的話我們可以再看一個例子:
var a = []; for (let i = 0; i < 10; i++) { let val = i; a[i] = function () { console.log(val); }; } a[6](); // 6
這時候你就會理解原因了,就相當于for循環中的執行體,每次的執行都位于一個多帶帶的代碼塊中。這個val是我們顯示定義的一個副本,當我們執行a[6]的時候,他會找到a[6]保存的函數的執行環境下去找這個val,數組a中的每個元素都位于一個多帶帶的代碼塊中互不影響。那么我們可以得出一個結論:js引擎會為我們for循環中每次循環的代碼塊保存一個副本。
Nicholas C. Zakas的《深入理解ES6》中也有相關解釋。
不存在變量提升
console.log(a);// undefined console.log(b);// b is not defined var a = 1; let b = 2;
暫時性死區
只要塊級作用域中存在let命令,那么let聲明的變量就會綁定這個作用域不受外部影響。
var temp = "hello"; if(true){ console.log(temp);// temp is not defined let temp; } 原因就是let綁定了塊級作用域并且let定義的變量不會提升,就是這個地盤跟我同名的都得死。 隱蔽的死區 function test(x = y, y = 2) { return [x, y]; } test();// 報錯
原因是:當執行test()的時候會先將y的值賦給x作為初始值,但此時y不存在,所以報錯。
function test(x = 2, y = x) { return [x, y]; } test();// [2, 2]
這樣就沒問題了。
總之,暫時性死區的本質就是,只要一進入當前作用域,所要使用的變量就已經存在了,但是不可獲取,只有等到聲明變量的那一行代碼出現,才可以獲取和使用該變量。
不允許重復聲明
let不允許在同一作用域聲明兩個相同的變量。
let a; var a;//報錯 a已經被聲明了
function fun(params) { let params; } func();//報錯 params已經被聲明了 function test(params) { {//內部代碼塊 let params; } } test();//正常執行 執行函數內部的代碼塊被其中的那個變量占用了而已
塊級作用域
先看一下es5,es5只有全局作用域和函數作用域。
var name = "Jason"; function test() { console.log(name); if(false) { var name = "Nico"; } } ==>相當于 var name = "Jason"; function test() { var name;//變量提升 console.log(name); if(false) { name = "Nico"; } } 所以執行test()會打印undefined
還有就是for循環的時候i的定義被提前
for(var i = 0; i < 3; i++) { console.log(i); } console.log(i); 依次打印0 1 2 3
原因是i定義被提前,如下:
var i; for(i = 0; i < 3; i++) { console.log(i); } console.log(i);
es6出現了塊級作用域
function test() { let n = 0; if(true) { let n = 1; } console.log(n); } test();// 0
外層的塊級作用域不受內層的控制。
{ { let a = 1; } console.log(a);//報錯 a未被定義 }
外層作用域無法訪問內層作用域定義的變量
{ let a = 0; { let a = 1; } }
內層作用域可以命名外層已經命名的變量。
值得提醒的是函數在塊級作用域中的聲明
function test() { console.log("outside"); } (function() { if(false) { function test() { console.log("inside"); } } console.log(test()); })();
ES5會打印inside字符串,ES6卻會報test is not a function的錯。
是不是很詫異,為什么ES6沒有打印outside呢?
原因是:ES6中允許塊級作用域中聲明函數,但是函數聲明會類似于var提升到全局作用域或者函數作用域頭部,同時函數聲明會提升到塊級作用域頭部,所以上面的代碼就相當于
function test() { console.log("outside"); } (function() { var test = undefined; if(false) { function test() { console.log("inside"); } } console.log(test()); })(); 所以才會報test is not a function的錯誤。
所以盡量避免塊級作用域中聲明函數,如果有必要的話可以使用函數表達式。
function test() { console.log("outside"); } (function() { if(false) { let test = function() { console.log("inside"); } } console.log(test());// outside })();
const命令
用于定義常量,一旦定義必須立刻初始化不然報錯,定義后無法改變值,改變也會報錯。
const USER_NAME;//報錯
const USER_ID = "410100"; USER_ID = 2;//報錯
const的作用域與let命令相同:只在聲明所在的塊級作用域內有效
const命令聲明的常量也是不提升,同樣存在暫時性死區,只能在聲明的位置后面使用。
const聲明的常量,也與let一樣不可重復聲明。
const其實保證的是變量存儲的內存地址不得改動,對于簡單的數據類型(數值,布爾,字符串),值就存在內存地址指向的位置,就等同于常量。但是對于數組、對象保存的就是一個指針,只能保證這個指針不被改變。對于內部的數據結構的變化是無法控制的。
const ARR = []; ARR.push(1);// 可以執行 ARR.length = 0;// 可以執行 ARR = [];//報錯
const OBJ = {}; OBJ.name = "JASON";// 可以執行 OBJ = {};//報錯
ES6 聲明變量的六種方法:var function let const import class
頂層對象:瀏覽器中指window Node中指global
ES5的時候全局變量的賦值與頂層變量的賦值是同一件事。
ES6改變了這一點除了var與function還保持原來的方式,新的聲明變量的方法不再與頂層變量掛鉤。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90573.html
摘要:和命令命令是在它所在的代碼塊有效,它屬于塊級作用域,新增。只有全局作用域和函數作用域。 let和const命令 let命令是在它所在的代碼塊有效,它屬于塊級作用域,es6新增。es5只有全局作用域和函數作用域。let命令存在暫時性死區(TDZ),即在申明前使用就會報錯,不存在變量提升 console.log(a); // 報錯 let a = 111; ==let不允許在相同作用域中,...
摘要:類似于數組,但是中不存在重復元素??梢越邮芤粋€數組或者其他具有接口的數據結構作為參數從上面的代碼可以看出有去重的功能。去重還有另一個方法將數據結構的數據轉換成數組。清除實例的指定成員。返回一個布爾值,表示某個值是否在實例之中。 Set Set類似于數組,但是Set中不存在重復元素。Set可以接受一個數組(或者其他具有itarable接口的數據結構)作為參數 const set = ne...
摘要:數組的解構賦值規定允許按照一定模式,從數組和對象中提取值對變量進行賦值,我們稱之為解構。的規則是,只要有可能導致解構的歧義,就不得使用圓括號。 數組的解構賦值 ES6規定:允許按照一定模式,從數組和對象中提取值對變量進行賦值,我們稱之為解構。以前賦值只能直接指定值 let a = 1; let b = 2; let c = 3; ES6允許以下這種做法 let [a, b, c] = ...
摘要:與字符編碼通過指定的編碼進制,可以在與普通的字符串之間轉換。中文中文通常用于實例數組的排序。有點像方法合并截斷為的長度,缺少的部分會用補充,是一個返回,是一個支持的字符編碼返回,創建并返回一個形式的迭代器,如果與具有完全相同的字節就返回 Buffer 可以在TCP流或者文件系統操作等場景中處理二進制數據流。 Buffer實例類似于整數數組,但是Buffer大小固定、且在V8堆外分配物理...
摘要:核心模塊學習之何為在引入之前,沒有能讀取和操作二進制數據流的機制,作為引入,以便能和網絡流文件流等進行交互。返回值寫入的實際大小,沒有足夠的空間保存,只會寫入一部分。返回值實際存入的字節數。參考文章一進階核心模塊常用使用總結 node 核心模塊學習之Buffer 何為 Buffer 在ES6引入 TypeArray 之前,JS沒有能讀取和操作二進制數據流的機制,Buffer 作為 No...
閱讀 2947·2023-04-25 22:16
閱讀 2093·2021-10-11 11:11
閱讀 3248·2019-08-29 13:26
閱讀 593·2019-08-29 12:32
閱讀 3410·2019-08-26 11:49
閱讀 2988·2019-08-26 10:30
閱讀 1939·2019-08-23 17:59
閱讀 1507·2019-08-23 17:57