第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:
本来是写一个给自己看的类似笔记的东西,怎么写写写搞得跟教程似的。。。可能内心有一种想当老师的莫名的优越心态。。。这不好。。。我的技术也还着实很烂。。。。
另外也太浪费时间。。。。。。。。这啥时候能把这些过一遍。。。。还有很多东西要学。。。。
其实内容不多,但写的很多。。。。
自己忘了回头看也麻烦。。。。
还是得换种方式,更像笔记一点,更精炼一点。