let、const和块级作用域
块级作用于关于强范例言语履历的人应当非常好明白, 一言以蔽之:ES5对变量作用于分开运用了函数(词法作用域), 而ES6运用花括号(块作用域)。
关于词法作用域在 javascript函数、作用域链与闭包 中有细致的诠释。关于let 和 const声明的变量在花括号的支解下同样会构成作用于链(内部接见外部的, 但外部不能接见内部)。然则花括号关于没有声明直接定义以及用 var 声明的变量没有影响, 这些变量依旧恪守词法作用域划定规矩。
关于let 和 const 最大的优点就是避免了能够的运行时毛病, 不过也有直观的优点:
- 用块(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 定义函数不具有块级作用域。
但我们须要注重的一下几点:
- 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
, 也就是其指向的数据地点内存地区可读可写, 然则指针的值初始后就不能改。
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对象、类与原型链
- 跨模块常量
关于跨模块的常量, 能够如许写:
// 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