{let a =1;var b =2;functions(){return a;} console.dir(s);/*
...
[[Scopes]]: Scopes[2]
0: Block {a: 1}
1: Global ...
*/}// 此处不能使用 a ,a 是块级作用域// 此处可以使用 b , b 在此处是全局作用域
functioncounter(){var arr =[];for(var i =0; i <3;++i){ arr[i]=function(){return i;}}return arr;}var coun =counter();for(var i =0; i <3;++i){ console.log(coun[i]());// 3 3 3}
functioncounter(){var arr =[];for(let i =0; i <3;++i){ arr[i]=function(){return i;}}return arr;}var coun =counter();for(var i =0; i <3;++i){ console.log(coun[i]());// 0 1 2}
当然也可以使用匿名函数新建函数作用域来解决
functioncounter(){var arr =[];for(var i =0; i <3;++i){(function(i){ arr[i]=function(){return i;}})(i);}return arr;}var coun =counter();for(var i =0; i <3;++i){ console.log(coun[i]());// 0 1 2}
let a =1;let a =1;//Uncaught SyntaxError: Identifier 'a' has already been declaredconst b =1;const b =1;//Uncaught SyntaxError: Identifier 'b' has already been declared
let 的「创建」过程被提升了,但是初始化没有提升。
var 的「创建」和「初始化」都被提升了。
function 的「创建」「初始化」和「赋值」都被提升了。
在stackoverflow中比较有说服力的例子
x ="global";// function scope:(function(){ x;// not "global"var/let/… x;}());// block scope (not for `var`s):{ x;// not "global"let/const/… x;}
js中无论哪种形式声明var,let,const,function,function*,class都会存在提升现象,不同的是,var,function,function*的声明会在提升时进行初始化赋值为 undefined,因此访问这些变量的时候,不会报ReferenceError异常,而使用let,const,class声明的变量,被提升后不会被初始化,这些变量所处的状态被称为temporal dead zone,此时如果访问这些变量会抛出ReferenceError异常,看上去就像没被提升一样。