① - var、let、const - JS变量声明和作用域

如题所述

第1个回答  2024-08-20
个人学习笔记,对基础知识的整理和巩固。#[1]

Javascript有三种声明方式[2]:

可通过这三种方式对变量进行声明,变量必须进行声明才可以使用(非声明变量的特例会再述),如:

变量的赋值

const必须在声明的同时赋值,并且不允许二次赋值。

var和let可以不在声明的时候赋值,也可以多次赋值。未赋值变量初始值为undefined。

const与let除此之外没有其他区别,故以下讨论只区分var和let,对const的理解可以直接带入let。

作用域

var作用域

var声明作用于全局或函数内,声明在函数内的作用于该函数内,声明于函数外的作用于全局。(可不妨理解为叫“函数内作用域”。)

块作用域

let和const均为块(大括号)作用域。变量仅在该代码块内生效,写在顶端的在全局生效。

变量名的共存问题

同一作用域(完全相同,包含关系等不算相同)内同一名称的变量只能存在一个,如果对同一名称进行了多次声明:

var的可重复声明特性使得,即使忘记了变量已经声明从而又一次声明,代码也可以正常运行,但在很多时候可能会造成变量重名等问题。

所以应该尽量避免重复声明。

不同作用域内同一名称的变量可以同时存在,变量的“指向”以“局部”为先,逐级上溯:

#[1]

变量声明的提升

代码执行前,变量声明会被提升,即不论声明写在哪一行,在该变量作用域内任何代码执行前即认为变量已声明。

事实上,MDN认为只有var声明会被提升[6],但是我觉得认为let和const声明也会被提升对于有些问题会非常好理解,并且不会影响到事实情况。如有不妥,还请指正。

其实变量的提升也可以理解为,该作用域内有没有声明变量。

暂存死区问题

这是一个能不能提前使用的问题,MDN把它叫做“暂存死区”。

即:let(const)声明的变量不能在声明位置前使用。

事实上,在"预处理"时,所有的声明被“注册”,var声明的变量会分配一个初始值(undefined),而let不会,只有执行到声明语句时,let声明的变量才会被初始化,而未初始化的变量不能使用。从let变量作用的块顶部到声明位置被称作“暂存死区”。

我们已经认为let声明也可以被提升,所以针对此处,let声明被提升,但是它声明的变量不能在声明位置之前使用。

而var可以:

来看下一个例子:

变量声明会被提升,所以,虽然在①处时,块内的声明尚在下一行,但是块内变量a实际上已经声明,又因为let声明的变量不能在声明位置前使用,所以抛出了错误。

而对于var:

另外还有两个相关的特殊例子:

let与for循环的特殊情况

for循环初始化语句中用let声明的变量会在流程中经过特殊处理,详情参见另一篇笔记: let与for循环 。

非声明变量(直接赋值变量)

如果不声明,直接为一个变量赋值,则会在全局对象(window)创建一个相应的属性,事实上,就可以认为它不是一个变量,而是全局对象的属性,仅此而已。它甚至可以通过delete删除:

即使在函数内,也会创建为全局属性。

这种方式创建的变量(全局对象的属性)不会被提升(因为它根本没有声明变量),只有在执行时才会产生。

顶层声明的var变量

在顶层声明的var变量也会成为全局对象的属性,但不能通过delete删除。

变量的连续赋值

const变量指向对象和数组

const变量(常量)不能重新赋值。但是如果常量指向对象或数组,其可被修改。

typeof运算符的特殊情况

使用未声明的变量会报错,但是typeof特殊:

主要内容的总结:

此篇仅为个人学习总结,大多为个人理解,专业性差,非教程,并不权威,也并不一定都正确。

如有错误,提前道歉,也欢迎指正。

如与其他有冲突,请以权威为准。

PS:

本来是写一个给自己看的类似笔记的东西,怎么写写写搞得跟教程似的。。。可能内心有一种想当老师的莫名的优越心态。。。这不好。。。我的技术也还着实很烂。。。。

另外也太浪费时间。。。。。。。。这啥时候能把这些过一遍。。。。还有很多东西要学。。。。

其实内容不多,但写的很多。。。。

自己忘了回头看也麻烦。。。。

还是得换种方式,更像笔记一点,更精炼一点。
相似回答
大家正在搜