ECMAScript6(1):塊級做用域

let、const和塊級做用域

塊級做用於對於強類型語言經驗的人應該很是好理解, 一言以蔽之:ES5對變量做用於分隔使用了函數(詞法做用域), 而ES6使用花括號(塊做用域)。
對於詞法做用域在 javascript函數、做用域鏈與閉包 中有詳細的解釋。對於let 和 const聲明的變量在花括號的分割下一樣會造成做用於鏈(內部訪問外部的, 但外部不能訪問內部)。可是花括號對於沒有聲明直接定義以及用 var 聲明的變量沒有影響, 這些變量依然遵照詞法做用域規則。javascript

對於let 和 const 最大的好處就是避免了可能的運行時錯誤, 不過也有直觀的好處:java

  • 用塊(Blocks)替換當即執行函數(IIFEs)
  • 定義循環變量不會外泄
  • 循環定義函數能夠不用閉包了
  • 能夠放心的在 if 等條件中定義函數
//用塊(Blocks)替換當即執行函數(IIFEs)
//ES5
(function () {
  var food = 'Meow Mix';
}());
console.log(food); // Reference Error

//ES6
{
  let food = 'Meow Mix';
}
console.log(food); // Reference Error
var a = [];
for(let i = 0; i < 10; i++){
  a[i] = function(){
    console.log(i);
  }
}
a[6]();       //這裏輸出6, 在var定義i的for循環中輸出 10
console.log(i);    //ReferenceError
function b(){console.log("outside");}
function f(){
  if(false){
    function b(){console.log("inside");}
  }
  b();
}
f();   // ES5 中報錯:"TypeError:b is not a function" 而 ES6 中輸出"outside"

由此例能夠看出 function 定義函數不具備塊級做用域。c++

但咱們須要注意的一下幾點:segmentfault

  • let 和 const 聲明的變量不在 window 的屬性中
var a = 10;
let b = 20;
const c = 30;

console.log(window.a);    //10
console.log(window.b);    //undedined
console.log(window.c);    //undedined
  • let 和 const 聲明的變量沒有聲明提早, 因此在做用域內存在暫時性死區
var temp = 20;
(function area(){
  console.log(temp);  //undefined
  var temp = 30;      //聲明提早
}());
if(true){
  console.log(temp);  //ReferenceError   可是 babel 會獲得 undefined
  let temp = 20;
}
//一個隱蔽的死區
function bar(x = y, y = 2){
  console.log(x, y);
}
bar();    //報錯, 由於定義 x 的時候, y 尚未定義 (babel 中不報錯,獲得 undefined 2)
function par(x = 2, y = x){
  console.log(x, y);
}
par();    //22
  • let 和 const 聲明變量在當前做用域(不包括做用域鏈)上不能重複。const聲明的變量必須初始化, 且不能修改:
let a = 10;
var b = 20;
const c = 30;

let a = 4;    //報錯
const b = 3;  //報錯
c = 20;   //報錯, c是隻讀的
  • 不能夠連續定義變量
let a=b=3;     //報錯 b 未定義
const c=d=2;   //報錯 d 未定義
  • 技巧:ES6 中, 在塊做用於外調用內部函數
var f;
{
  f = function(){
    console.log("inside");
  }
}
f();
  • const 聲明的基本變量不可改變, 但複雜變量能夠改變其內容

const 這個特性和底層的 c++ 一致, 在 c++ 中 const 至關於常指針 int * const p, 也就是其指向的數據所在內存區域可讀可寫, 可是指針的值初始後就不能改。babel

const a = 10;
const b = {
  num: 20
};
b.num = 30;
console.log(b.num);   //30
a = 20;         //TypeError
b = {
  num: 90
};              //TypeError

若是想讓非基本變量內部也不可改變, 須要使用 Object.freeze() 方法。能夠參考:javascript對象、類與原型鏈閉包

  • 跨模塊常量

對於跨模塊的常量, 能夠這樣寫:ide

// const.js module
export const A = 1;
export const B = 2;

// test.js 文件
import * as constants from './const';
console.log(constants.A);   //1
console.log(constants.B);   //2
//or
import {A, B} from './const';
console.log(A);   //1
console.log(B);   //2
相關文章
相關標籤/搜索