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

聊一聊变量提升和时间死区 #6

Open
H246802 opened this issue Mar 14, 2019 · 0 comments
Open

聊一聊变量提升和时间死区 #6

H246802 opened this issue Mar 14, 2019 · 0 comments

Comments

@H246802
Copy link
Owner

H246802 commented Mar 14, 2019

前言

看了方应杭老师的一篇解释 let 的文章,对JavaScript中的声明有了深刻的理解,模仿着按着自己思路写了些这篇文章

从块级作用域说起

在我刚刚开始学前端的时候,那时候还是处于2016年的年中,也是前端最火的时候。第一次学到 JS 的时候,我记得我看的是网课,课上老师斩钉截铁的说 JS 不存在块级作用域。因此也就有了一些关于作用域的考题。例如:

for (var i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(new Date, i);
    }, 1000);
}
console.log(new Date, i);  // ?输出结果是多少

对于早已将答案背下来的我,自然可以自信的答下 5,间隔一秒后连续输出五个5,对应的如何输出 0,1,2,3,4,自然也有了答案:

for (var i = 0; i < 5; i++) {
    (function(i){
		setTimeout(function() {
        	console.log(new Date, i);
    	}, 1000);
	})(i)
}

es6 出现之前,那位老师说的是没错的,在2015年的时候 es6 出现了。从此 JavaScript 有了它的块级作用域。对于上题也就有了更好的答案。

for (let i = 0; i < 5; i++) {  
	setTimeout(function() {
       	console.log(new Date, i);
   	}, 1000);
	
}

因此我就带着对神奇的 let 疑问去学习了它。

第一次认识 let

对于一个新的知识,我认识到 let 还是从 MDN 的文档入的手。

let 语句声明一个块级作用域的本地变量,并且可选的将其初始化为一个值。

image

第一次认识 let ,匆匆的过去了,得到的就这么些信息。

  • let 同一作用域不存在变量提升,没有初始化为 undefined 的过程
  • let 使用后可以使 {} 存在块级作用域
  • let 在同一作用域不能存在多次赋值

这是简单获取的信息,但在阅读完 方应杭 老师的这篇文章后,又获取了更多的信息。

JavaScript中变量声明机制

在文章中提出来一个在此之前我不曾了解的信息。

对于我们所了解的变量的声明以及函数声明,在JavaScript中一般是存在创建create、初始化initialize 和赋值assign三个过程的,在这三个过程中:

创建:即在变量所在作用于头部抛出变量,仅仅是抛出,是不能被使用的;
初始化:在变量初始化之前变量是不能被使用的,初始化只有一次,初始化之后变量可以使用;
赋值:即覆盖初始化的值

在let、var、const(包括函数声明)的声明过程中,他们的创建create、初始化initialize 和赋值assign是有区别的。

对于 let

{
  let x = 1
  x = 2
}
  1. 找到所有用 let 声明的变量,在环境中「创建」(create)这些变量
  2. 开始执行代码(注意现在还没有初始化)
  3. 执行 x = 1,将 x 「初始化」(initialize)为 1(这并不是一次赋值,如果代码是 let x,就将 x 初始化为 undefined)
  4. 执行 x = 2,对 x 进行「赋值」(assign)

对于 var

function fn(){
  var a = 1
  var a = 2
}
fn()
  1. 执行 fn 时,创建 fn 函数作用域
  2. 找到 fn 中所有用 var 声明的变量,在这个环境中「创建」a 变量
  3. 将变量 a「初始化」为 undefined
  4. 开始执行代码
  5. a = 1 将 a 变量「赋值」为 1
  6. var a = 2 将 a 变量「赋值」为 2

对于 const

const声明创建了一个常量
const和let比较像,也是块级作用域,区别就是,const在定义的时候必须初始化,而且不能被赋值,不能使用 const a

{
  const str = 'str'
}
  1. 找到所有用 const 声明的变量,在环境中「创建」(create)这些变量
  2. 开始执行代码(注意现在还没有初始化)
  3. 执行 x = 1,将 x 「初始化」(initialize) 并「赋值」为 'str'

总结

最后可以用一张表格进行总结

-- var let const
变量/常量 变量 变量 常量
作用域 函数作用域 块级作用域 块级作用域
创建 作用域顶部创建 作用域顶部创建 作用域顶部创建
初始化 let语句 作用域顶部 const语句
赋值 可以赋值 可以赋值 报错
重复声明 报错 可以重复声明 报错
暂时性死区 没有
@H246802 H246802 changed the title 聊一聊变量提升 聊一聊变量提升和时间死区 Mar 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant