在es6之前用var定义变量。
es6中新增了let、const
变量声明提升
所谓变量声明提升指的是,用var定义的变量和函数声明,会被提升到当前作用域的顶部。
var定义的变量,是将变量本身提升到作用域顶部。
而函数声明会把函数体一起提升到作用域的顶部。
fool(); //fool is not a function
foo(); //222
var fool = function(){
console.log(111);
}
function foo(){
console.log(222);
}
从以上代码的输出结果来分析。var fool被提升到作用域顶端,但仅仅提升的只是这个变量的声明,并没有把变量的值提升,所以在没有执行到
var fool = function(){...}
这一行时调用fool()会报错,说fool这个方法没有定义。
foo()是个函数声明,函数声明的提升会把函数体一起提升,所以在执行foo()方法的时候会执行function foo(){...}这个方法。
let
let没有声明提升
在作用于内部用let定义的变量,和外部作用域没有关系
所以内层的同名变量不会覆盖外层的变量
function f1(){
let n=5;
if(true){let n=10;}
console.log(n);//5
}
从上面的代码的执行结果可以看出,内部的代码块定义的n并没有覆盖外部定义的n。
const
const用来定义值不能改变的变量(常量),所以用const定义了之后要立即给常量赋值
要注意的是,当用const来定义一个对象的时候,const定义的变量名指向的是对象的地址,而不是对象的值。所以此时只是保证对象的地址不变,并不能保证对象内部的数据不变。
const f = {};
f.name = "snail";
此时,如果要冻结对象,要使用Object.freeze()方法。这样定义出来的对象无法进行修改。
const f = Object.freeze({});
f.prop = 123; //失效
因为let和const都不存在变量提升,所以可能存在暂时性死区。即在没有执行到变量定义那一行之前使用变量会找不到变量。成为暂时性死区。
let和const都不允许重复声明
-
在ES6中,var命令和function命令声明的全局变量依旧是全局对象的属性。但是let,const,class命令声明的全局变量不属于全局对象的属性。
var a = 1;
window.a; //1
let b = 2;
window.b; //undefined -
ES6规定,函数本身的作用域在其所在的块级作用域之内
function f(){console.log(1111);}
(function(){
if(false){
function f(){console.log(2222);}
}
f(); //1111
}())
以上代码的执行结果来看,因为es6没有函数声明提升,所以匿名立即执行函数里的f()不会提升。所以f()执行时还是全局里的定义。