1.变量的声明与引用

作用域

在ES6中,添加了块级作用域,所以就有全局作用域、函数局部执行环境、块级作用域三类作用域。js代码的作用域以全局作用域为根,向下以树状的数据结构展开。

作用域查找变量的原则是,现在自身的作用域中从最顶部的代码到引用变量的地方,这个范围内进行查找,找不到的话只能向外面的作用域中查找,而不会向内部的作用域中查找。


未声明的变量

在js中,调用未声明的变量,会直接报错。


var声明

var的声明和查找,只承认全局作用域和函数局部执行环境,块级作用域会忽视。

用var重复声明变量的话,后声明的会覆盖之前声明的。

var声明的变量会在当前作用域中得到变量提升,相当于在作用域一开始就声明变量(但是不会初始化),因此在作用域的任何地方,甚至var声明的变量之前调用,不会报错,而是显示未初始化的undefined。


let声明

与var和不同的是,let的声明和查找,全局作用域、函数局部执行环境和块级作用域都承认。

用let重复声明变量的话,只要之前声明过了的变量,无论用什么声明的,都会报错。

如果在let声明之前调用变量的话,报错的。但是,在它的上级作用域中也声明一个变量的话,并不会沿着作用域链去查找调用,还是报错。所以个人认为,let也存在变量提升,不过,提升后的作用与var不一样,let不会将变量置顶,而是形成一个“暂时性死区”(temporal dead zone,简称 TDZ),使得作用域顶部到let声明变量的范围内,不能使用该变量。


const声明

const可以看作,在let的基础上,添加了一开始必须初始化,并且不能再改变变量的限制。

其他的,与let类似。


function声明

function的声明和查找,与全局作用域、函数局部执行环境和块级作用域的关系比较松散混乱,所以就有点奇怪了=。=

在同一作用域的时候,function声明与var一样,会在当前作用域中得到变量提升。当时,与var不同的是,它会直接把初始化的函数内容也一起提升。

在同一作用域的时候,若是在一个作用域中同时进行两次函数声明的话,第二个函数会直接覆盖第一个。

严格模式中,在块级作用域中重复声明会报错,全局作用域中和函数执行作用域中则不会。

块级作用域内的块级作用域中声明函数是时:与let一样,承认块级作用域。

而在块级作用域与全局作用域混杂的时候。

全部块级内声明,在外部调用,像var一样:

一个在块级内声明,一个在外部声明:

这就非常有趣了,回到ES5,当var与function的声明重复时。

可以看到function的优先级使高于var,function会优先提升置顶,之后才是var。

所以,个人认为,在全局作用域下的块级作用域中的函数,对于全局作用域来说,是否看作var声明的函数变量?

函数执行作用域中,与全局作用域类似:

function在初始化的时候,只是一串静态的代码,无论内部引用什么变量,都不会有异常,只有在调用的时候,才会根据作用域链进行查找变量。

而内部变量查找的话,并不是从调用函数的地方开始,而是以声明的地方为起点,进入作用域链查找变量。(函数名可以视作使指向函数代码区的一个地址)。


小结

以上代码都是在Chorme版本 83.0.4103.97(正式版本)浏览器上执行。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值