ES6学习笔记第二章
let 和 const命令
1 let命令
用法:
ES6新增let命令,用于声明变量,用法类似var,只是let声明的变量是块级作用域内有效
例:
{
let a = 10;
var b = 1;
}
a // a is not defined
b // 1
根据返回值可以看出,let声明变量时的作用域只在其代码块内
for 循环的计数器就很适合使用let来声明变量。
var a = [];
for (var i = 0; i<10; i++){
a[i] = function(){
console.log(i);
};
}
a[6]();//10
如果用let声明变量i;
a[6]();//6
因为let声明的i只在本轮循环内有效。所以每次循环的i其实都是新的变量,于是输出6。
let声明变量不存在变量提升;
例:
console.log(foo);
let foo = 2;
执行会报错,但是如果用var声明,得到的结果就是2。
暂时性死区:
只要块级作用域内存在let命令,它所声明的变量就"绑定这个区域",不受外部影响。
例
var tmp =123 ;
if(true){
tmp = 'abc';
let tmp;
}
报错,let绑定了if内的块级作用域,在let声明变量前,对tmp赋值会报错。
ES6明确规定,如果区块 存在let和const命令,则这个区块对这些命令声明的变量从一开始就形成封闭作用域。
在代码块内,使用let命令声明变量之前,该变量都是不可用的。语法上称"暂时性死区",简称TDZ。
let不允许在相同作用域内重复声明同一个变量。(这个就不解释了)
2.块级作用域到底是个啥
ES5只有函数作用域和全局作用域,没有块级作用域,那么会带来以下不合理情况:
例1
var tmp = new Date();
funciton f(){
console.log(tmp);
if(false){
var tmp = "hello world";
}
}
f() //undefined;
变量提升内层tmp变量覆盖了外层的tmp变量
例2
for 循环计数的变量泄露为全局变量。
ES6的块级作用域
function f1(){
let n = 5;
if(true){
let n = 10;
}
console.log(n);//5
}
最后输出5,表明外层代码不受内层代码块的影响。如果使用var, 最后的输出值为10.
ES6允许块级作用域任意嵌套;
另外ES6规定,函数本身作用域在其所在的块级作用域内。
fuction f(){ console.log(1)};
(function (){
function f(){
console.log(2);
}
f();
}());
ES5//2,
ES6//1。
严格模式下,函数只能在顶层作用域和函数内声明,其他情况(if,for)下的声明都会报错。
3.const命令
const 用来声明常量。 一旦声明,其值不可改变。
const 作用域等同于let,只在声明所在的块级作用域内有效。
const 命令只是保证变量名指向的地址不变,并不保证该地址的数据不变,所以将一个对象声明为常量必须非常小心。
例
const a=[];
a.push("hello");//可执行
a.length = 0; //可执行
a = ['Dave'];// 报错。
数组本身是可写的,但是要把另一个数组赋值给a,就会报错。
如果想让对面被冻结,本身也不可写,应该使用Object.freeze方法。
ES6一共6中声明变量的方法:
var function let const import class
4.跨模块常量
// constants.js 模块
export const A= 1;
export const B= 3;
export const C= 4;
// test1.js 模块
import * as constants from './constants';
console.log(constanst.A);//1
console.log(constanst.B);//3
//test2.js模块
import {A,B} from './constants';
console.log(A);//1
console.log(B);//3
5.全局对象的属性
ES5:
window.a = 1;
a //1;
a = 2;
window.a //2
ES6:
let b = 1;
window.b // undefined;
ES6规定 var 命令和function 命令声明的全局变量依旧是全局对象的属性
let命令 、 const命令、 class命令声明的全局变量不属于全局对象的属性