变量, 是编程语言的核心,也是编程语言的灵魂。那么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
通过访问属性并修改值这种方式谨慎使用,修改的属性过多时,还是键值对合并之后保存到一个新常量中较为妥当