1、let
6新加了let命令,用来声明变量,和var类似。
但其声明的变量只在let命令所在代码块内访问,之外访问不了。
{
let a=1;
var b=1;
}
console.log(a,b) // a not defined
它可用于for循环中
var a=[];
for(let i=0;i<10;i++){
a[i]=function(){
console.log(i):
}
}
a6;//输出6
在每次for循环时i 都会一个新的变量,i只在本地循环中可用。
它只在本地循环的块中可访问。
let 使用前必须先申明。
暂时性死区:
只要块级内有let命令,它所声明的变量会绑定在这个块上,不受外部影响。
var tmp = 123;
if (true) {
tmp = 'abc';
let tmp;
}
解析:这里全局有个tmp在块内赋值了,后才创建的let tmp。
在此块内创建了let ,但在申明前使用了它会报错的。
es6明确规定,如果块内存在let const ,这些变量会形成封闭作用域,凡是在声明前使用都会报错。
如果当全局内和块内的let名称一样,先使用变量是不会向上级查找的。
不允许重复声明:
let在块内不允许重复声明同样的变量。
Let a;
var a;
这时var 会报错。
当然函数内的声明不能和参数名一样。
2、块级作用域
为什么需要呢?
es5里只有全局作用域和函数作用域,是没有块级作用域的。
问题1:
var tmp = new Date();
function f(){
console.log(tmp);
if (false){
var tmp = "hello world";
}
}
f() // undefined
执行后会输出未定义
原因是函数内的声明变量提升,在访问时会输出未定义,而不会到全局去找变量。
这样内部变量覆盖了对全局的访问。
问题2:
for(var i=0;i<10;i++){}
console.log(i); //9
for 循环定义的i 在结束后还能访问到。
所以let实现了块级作用域。
function fn(){
let n=5;
if(true){
let n=10;
}
console.log(n)//5
}
因为有了块作用域if内的let不会覆盖到外部的。
es5允许块作用域任意嵌套。
{{{let a=1;}}}
块作用域的出现使得立即执行函数没那么重要了。
函数中的function 函数会提升,会覆盖掉全局的访问。这是es5时
es6是不会的。
声明的let 在块是可以访问和修改的。
3、const命令
它声明的是常量。不需要改变的值。
声明时必须要赋值的.
const的作用域和let一样的。
在声明复合类型的常量时,变量名指向的是数据的地址.
const命令只保证常量指定的地址不变,并不保证地址指向的数据不变。
const a=[];
a.push(1);
a=[1,2]
赋值会报错
可以将对象冻结,来实现不允许修改对象。
const a=Object.freeze({});
a.name=Xx;
添加属性时会报错。
上边创建一个冻结的对象,不可对其操作的。
4、跨模块常量使用
const声明的常量只能在当前代码使用,当然也可跨模块使用
// constants.js 模块
export const A = 1;
export const B = 3;
export const C = 4;
// test1.js 模块
import * as constants from './constants';
console.log(constants.A); // 1
console.log(constants.B); // 3
// test2.js 模块
import {A, B} from './constants';
console.log(A); // 1
console.log(B); // 3