变量, 是编程语言的核心,也是编程语言的灵魂。那么JavaScript中的变量是怎么回事?
之前我写过一篇JavaScript中的四兄弟,介绍了JavaScript中声明变量的四种方式var
,function
,let
和const
。我就知道那个时候我就挖了一个坑,这篇文章我们详细一些。
JavaScript中的变量可以在两个维度进行分类,①域, ②可变性
域 | 可变性 |
---|---|
全局 | 值可变量 |
局部 | 常量 |
什么是域? 可访问、操作一个变量的区域(范围)。有顶层域,也叫全局域,也有局部域,局部域可在函数和{}内产生。在全局域内创建的变量就是全局变量,以此类推,在局部域内创建的变量
作用域是在定义的时候产生的
var name = 'jianyanzhi'; function say() { var name = 'jianyanzhi-say'; console.log(name); name = 'say-end-name'; console.log('say-end-name:', name); } say(); console.log(name);
上面这段代码哪些是全局变量哪些是局部变量呢?我们来分析一下。
图中,红框的部分就是全局域,在全局域中,我们创建了name
和say
两个变量。再缩小范围,绿框的部分就是由函数say
创建的局部域,在say
中只创建了name
这个变量,所以绿色下划线的name
变量就是局部变量。而函数say
中第三行又把name
这个变量重新赋值,此时操作的是局部变量。
var allowVar = 'jianyanzhi', allow = true; if (allow) { function allowFunction () { console.log('allow-say') } let allowLet = 'allowLet'; const allowConst = 'allowConst'; var allowVar = 'allowVar'; console.log('allow', allowFunction); console.log('allow', allowLet); console.log('allow', allowConst); console.log('allow', allowVar); } console.log('global', allowFunction); console.log('global', allowVar); console.log('global', allowLet); console.log('global', allowConst);
同样的问题,哪些是局部变量,哪些又是全局变量?我们来分析下;
代码执行的结果是什么?
allow "function allowFunction () {console.log('allow-say')}" allow "allowLet" allow "allowConst" allow "allowVar" global "function allowFunction () {console.log('allow-say')}" global "allowVar" ReferenceError allowConst is not defined // global "allowConst" ReferenceError allowLet is not defined // global "allowLet"
为什么会产生这样的结果?
if
条件语句中由var
和function
创建的变量,会自动归到if
语句所属的域中 因此我们看到global的输出中,var
和function
的输出和allow的输出是一致的。不只是if
语句,还有单纯的{}也是,比如{ var a = 1; function aFn() {} }
;var
和function
创建局部变量的时候,只能在function
中创建有效,var
是无法在{}块级作用域中创建局部变量的;let
和const
创建的变量则属于声明时所在的域,包括函数和{}。全局变量和局部变量的使用
全局变量作为持久性变量使用,全程有效,而不是拿来存储某个临时的值,谨慎修改
全局变量和局部变量存在同名的情况下,根据就近原则,优先使用局部变量,要防止污染全局变量
根据值的可变性来分类,可变的是变量,不可变的是常量。变量可后续随意更改,值是动态的,而常量一旦确定则无法修改,值是恒定、静态的。
var date = '2022-01-01'; const codeLang = 'JavaScript'; const articleData = { title: 'JavaScript中的变量', author: '简言之' }; date = '2022-04-04'; // success codeLang = 'Java'; // TypeError: Assignment to constant variable articleData = { title: 'haha', author: '简言之' } // TypeError: Assignment to constant variable articleData['title'] = 'haha'; // success
创建了两个常量和一个变量。变量date
后续可以随意更改,更改有效。
常量就无法更改了,codeLang
和articleData
在修改的时候抛出了类型错误。表示它们都是常量,无法更改。可为什么后面把title
改为haha
的时候就更改成功了?因为常量保存的是变量的值,这个值可以是一个普通值也可以是一个内存地址值,只要确保这个值是恒定的,其他由你使劲造。
变量与常量的使用
根据编码逻辑来适当使用常量,虽然变量可满足所有要求,但是合适使用常量可以增强代码的语义性
上述案例中的articleData
通过访问属性并修改值这种方式谨慎使用,修改的属性过多时,还是键值对合并之后保存到一个新常量中较为妥当