宝哥软件园

对JS中范围和可变吊装的深刻理解

编辑:宝哥软件园 来源:互联网 时间:2021-09-13

范围(范围)

对于Javascript初学者来说,最容易混淆的地方之一就是范围;其实不只是初学者。我见过一些有经验的javascript程序员,但是他们不太了解范围。Javascript范围令人困惑,因为它的程序语法本身看起来就像C族的语言。我对范围的理解是一个封闭的空间,只会影响一定的范围,不会影响外界。在这样的空间中,外部不能访问内部变量,但是内部可以访问外部变量。

c语言变量分为全局变量和局部变量。全局变量的作用域是任何文件和函数访问(当然,对于其他由不变量定义的C文件,应该使用extern关键字进行声明,也可以使用static关键字将作用域限制到当前文件)。局部变量的范围是从声明到由最近的花括号覆盖的块级别。Java没有全局变量,只有类变量、成员变量和局部变量。其作用范围根据访问权的公、受保护、私私私不同而有所不同,故在此不再赘述。

JS范围有哪些?

在ES5中,js只有两种范围形式:全局范围和函数范围。

全局范围实际上是全局对象的范围,可以在任何地方访问(如果它不在函数范围内)。

函数对象的范围与C的局部变量的范围不同,它的范围是整个函数范围,无论它在函数的任何位置声明!这就是所谓的吊装,也就是变量提升的概念。不过不用担心,下面会专门针对吊装做说明。

但是,在ES6中,添加了一个新的块级作用域(最新的花括号覆盖的作用域),但它仅限于通过let方式声明的变量。范围演示:

定义变量时,如果不写var,比如i=0,就定义为全局作用域的全局变量,否则就是函数作用域的局部变量。上面第一行中的var i=0被称为全局变量,因为它已经在全局区域中声明,并且不在函数的范围内,所以它与i=0相同。

至于为什么结果会这样,继续往下看。

申报单

变量声明:

函数声明:

可变提升(提升)

引出一个问题

下面的代码会输出什么?

我就这个问题采访了很多人,大部分都说输出就是日期。但是真正的结果是不确定的。为什么会这样?这就引出了一个概念——提升,在汉语中是变量提升的意思。MDN中可变吊装的解释如下:

无功提升

因为变量声明(以及一般的声明)是在执行任何代码之前处理的,所以在代码的任何地方声明变量就相当于在顶部声明变量。这也意味着一个变量在被声明之前可以被使用。这种行为被称为“提升”,因为变量声明似乎被移到了函数或全局代码的顶部。

这段话的翻译是

因为变量声明是在执行任何代码之前处理的,所以在代码区域的任何地方声明变量与在开头(顶部)声明变量是一样的。换句话说,似乎一个变量在声明之前就可以使用了!这种行为称为“提升”,即变量提升,看起来像是变量的声明被自动移动到函数或全局代码的顶部。

注意:只提升声明,不提升定义。

所以,上面的代码实际上是下面的形式:

因此,应该理解的是,当控制台输出时,tmp变量只声明而没有定义,因此输出应该是未定义的。

这里需要注意的是,虽然所有的声明(包括ES5的var和function以及ES6的function *、let、const和class)都会被提升,但是var、function和function *的提升和let、const和class是不一样的!具体原因可以在这里的解释中看到(大概意思是虽然let、const、class也升级了,但是不会初始化。此时访问它们时,它们会报告一个ReferenceError异常,直到语句执行完才会初始化,初始化前的状态称为时间死区)。让我们看一段代码来了解:

这里提升了A,但是因为它是稍后定义的,所以它输出未定义的

虽然A在这里升职了,但是却报了一个引用错误!

原因还是方式

为此,建议在声明变量时,将所有使用的变量都写在作用域(全局作用域或函数作用域)的顶部,这样代码看起来会更清晰,也更容易看出哪个变量来自函数作用域,哪个来自作用域链(本文就不多解释了,请自行阅读,有机会补充)。

重复申报

上面的输出实际上是1 2 2。虽然看起来X已经声明了两次,但是上面说js的var变量只有全局作用域和函数作用域,声明会被提升。因此,实际上X只会在顶部声明一次,var x=2的声明将被忽略,只用于赋值。也就是说,上面的代码实际上与下面是一致的。

函数和变量同时提升的问题

如果同时声明和定义函数和变量类型,会发生什么?请看下面的代码

A

上面的输出其实是:function foo(){},就是函数内容。

如果是这种形式呢

B

它的输出变成:未定义

为什么会这样?

原功能推广分为两种情况:

一个是函数声明。它是上面的函数foo(){}的形式

另一种:函数表达式。它是b的形式,var foo=function(){}

第二种形式其实是var变量的声明定义,所以应该理解为上面B的输出结果是未定义的。

函数声明的第一种形式会整体提升,包括函数定义的部分!所以,A相当于下面的方式!

原因如下:1 .函数声明被提升到顶部;2.声明只进行一次,因此var foo='i是text '的声明将被忽略。

并且函数声明的优先级优于变量声明,所以以下形式的输出也是函数内容:

摘要

要彻底了解JS的范围和余音,只需记住以下三点:

1.所有声明都将被提升到作用域的顶部

2.同一变量语句只执行一次,因此其他语句将被忽略

3.函数声明的优先级优于变量声明,函数声明会和定义一起提升

注意:

使用语句,可以临时更改运行时上下文的范围链。当访问未由var定义的变量时,将首先访问中对象的属性,然后沿着作用域链检查该属性。

以上就是本文的全部内容。希望本文的内容对大家的学习或工作有所帮助。有问题可以留言交流。

更多资讯
游戏推荐
更多+