Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ES6变量命名方式以及块级作用域 #8

Open
axuebin opened this issue Oct 16, 2017 · 0 comments
Open

ES6变量命名方式以及块级作用域 #8

axuebin opened this issue Oct 16, 2017 · 0 comments

Comments

@axuebin
Copy link
Owner

axuebin commented Oct 16, 2017

之前看《深入理解es6》的笔记。。。


var声明及变量提升机制

在ES6之前,在函数作用域中或者全局作用域中通过var关键字来声明变量,无论是在代码的哪个位置,这条声明语句都会提到最顶部来执行,这就是变量声明提升。

注意:只是声明提升,初始化并没有提升。

看一个例子:

function getStudent(name){
  if(name){
    var age=25;
  }else{
    console.log("name不存在");      
  }
  console.log(age); //undefined
}

如果按照预想的代码的执行顺序,当name有值时才会创建变量age,可是执行代码发现,即使不传入name,判断语句外的输出语句并没有报错,而是输出undefined

这就是变量声明提升。

块级声明

ES6前是没有块级作用域的,比如{}外可以访问内部的变量。

let声明

  • 声明变量
  • 作用域限制在当前代码块
  • 声明不会提升
  • 禁止重声明(同一作用域不行,可以覆盖外部同名变量)
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")时都会报错。

原因:

  • 在if语句内部执行之后,age变量将立即被销毁
  • 如果name为空,则永远都不会创建age变量

const声明

  • 声明常量
  • 必须初始化
  • 不可更改
  • 作用域限制在当前代码块
  • 声明不会提升
  • 禁止重声明(同一作用域不行,可以覆盖外部同名变量)

如果用const来声明对象,则对象中的值可以修改。

临时死区(Temporal Dead Zone)

JavaScript引擎在扫面代码发现声明变量时,遇到var则提升到作用域顶部,遇到letconst则放到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

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了~

之前,我们这样做 ~

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~

全局块作用域绑定

在全局作用域下声明的时

  • var会覆盖window对象中的属性
  • letconst会屏蔽,而不是覆盖,用window.还能访问到
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant