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
相关文章
相关标签/搜索