Open axuebin opened 7 years ago
之前看《深入理解es6》的笔记。。。
在ES6之前,在函数作用域中或者全局作用域中通过var关键字来声明变量,无论是在代码的哪个位置,这条声明语句都会提到最顶部来执行,这就是变量声明提升。
var
注意:只是声明提升,初始化并没有提升。
看一个例子:
function getStudent(name){ if(name){ var age=25; }else{ console.log("name不存在"); } console.log(age); //undefined }
如果按照预想的代码的执行顺序,当name有值时才会创建变量age,可是执行代码发现,即使不传入name,判断语句外的输出语句并没有报错,而是输出undefined。
name
age
undefined
这就是变量声明提升。
ES6前是没有块级作用域的,比如{}外可以访问内部的变量。
{}
function getStudent(name){ if(name){ let age=25; console.log(age); //25 }else{ console.log("name不存在"); } console.log(age); //age is not defined }
和上文一样的代码,只是将age的命名关键字从var改成了let,在执行getStudent()和getStudent("axuebin")时都会报错。
let
getStudent()
getStudent("axuebin")
原因:
如果用const来声明对象,则对象中的值可以修改。
const
JavaScript引擎在扫面代码发现声明变量时,遇到var则提升到作用域顶部,遇到let和const则放到TDZ中。当执行了变量声明语句后,TDZ中的变量才能正常访问。
我们经常使用for循环:
for(var i=0;i<10;i++){ console.log(i); //0,1,2,3,4,5,6,7,8,9 } console.log(i) //10
发现了什么?
在for循环执行后,我们仍然可以访问到变量i。
i
So easy ~ 把var换成let就解决了~
for(let i=0;i<10;i++){ console.log(i); //0,1,2,3,4,5,6,7,8,9 } console.log(i) //i is not defined
还记得当初讲闭包时setTimeout循环各一秒输出i的那个例子吗~
曾经熟悉的你 ~
for(var i=0;i<10;i++){ setTimeout(function(){ console.log(i); //10,10,10..... },1000) }
很显然,上面的代码输出了10次的10,setTimeout在执行了循环之后才执行,此时i已经是10了~
setTimeout
之前,我们这样做 ~
for(var i=0;i<10;i++){ setTimeout((function(i){ console.log(i); //0,1,2,3,4,5,6,7,8,9 })(i),1000) }
现在,我们这样做 ~ 来看看把var改成let会怎样~
for(let i=0;i<10;i++){ setTimeout(function(){ console.log(i); //0,1,2,3,4,5,6,7,8,9 },1000) }
nice~
在全局作用域下声明的时
window.
之前看《深入理解es6》的笔记。。。
var声明及变量提升机制
在ES6之前,在函数作用域中或者全局作用域中通过
var
关键字来声明变量,无论是在代码的哪个位置,这条声明语句都会提到最顶部来执行,这就是变量声明提升。注意:只是声明提升,初始化并没有提升。
看一个例子:
如果按照预想的代码的执行顺序,当
name
有值时才会创建变量age
,可是执行代码发现,即使不传入name
,判断语句外的输出语句并没有报错,而是输出undefined
。这就是变量声明提升。
块级声明
ES6前是没有块级作用域的,比如
{}
外可以访问内部的变量。let声明
和上文一样的代码,只是将
age
的命名关键字从var
改成了let
,在执行getStudent()
和getStudent("axuebin")
时都会报错。原因:
age
变量将立即被销毁name
为空,则永远都不会创建age
变量const声明
如果用
const
来声明对象,则对象中的值可以修改。临时死区(Temporal Dead Zone)
JavaScript引擎在扫面代码发现声明变量时,遇到
var
则提升到作用域顶部,遇到let
和const
则放到TDZ中。当执行了变量声明语句后,TDZ中的变量才能正常访问。循环中的块作用域绑定
我们经常使用for循环:
发现了什么?
在for循环执行后,我们仍然可以访问到变量
i
。So easy ~ 把
var
换成let
就解决了~还记得当初讲闭包时setTimeout循环各一秒输出i的那个例子吗~
曾经熟悉的你 ~
很显然,上面的代码输出了10次的10,
setTimeout
在执行了循环之后才执行,此时i
已经是10了~之前,我们这样做 ~
现在,我们这样做 ~ 来看看把
var
改成let
会怎样~nice~
全局块作用域绑定
在全局作用域下声明的时
var
会覆盖window对象中的属性let
和const
会屏蔽,而不是覆盖,用window.
还能访问到