JavaScript 各声明varletconst方式区别『详解』
Posted XianZhe_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript 各声明varletconst方式区别『详解』相关的知识,希望对你有一定的参考价值。
javascript 变量声明三种方式的区别『var、let、const』
文章目录
一、变量声明
变量的声明在每个编程语言里都会有,JavaScript的变量声明有var
、let
,常量的声明是const
。这几种声明方式的作用域有一定差别,以var
举例,以var
声明的变量会被隐式地创建为全局变量,并且还会产生变量提升的效果。
二、变量提升🎈
在讲解 var
、let
和 const
之前应了解什么是变量提升,这很重要。
先来看看这几行代码,判断是否能够正确打印不抛出异常
// 代码片段一
a = 1;
console.log(a); // 打印:1
// 代码片段二
var a = 1;
console.log(a) // 打印:1
// 代码片段三
console.log(a) // 打印:undefined
var a = 1;
// 代码片段四
console.log(a) // 抛出异常
// 代码片段五
var a = 1;
console.log(a) // 打印:1
// 代码片段六
console.log(a) // 打印:undefined
var a = 1;
console.log(a) // 打印:1
- 代码片段一: 即使没有使用声明符也能正常赋值和输出,这是因为在解析JavaScript代码的时候,将变量提前以
var
的方式进行了声明。 - 代码片段二: 正常以
var
进行声明的方式,结果当然能输出。 - 代码片段三: 神奇的是,程序也能正常输出并且不会抛出异常,但输出结果为
undefined
,这印证了在代码片段一中所说的,将变量提前以var
的方式进行了声明。 - 代码片段四: 二话不说总结打印一个为定义的变量时,那就不存在提前声明了,会抛出
ReferenceError
异常。 - 代码片段五: 对于块级代码块,能够调用全局的声明。
- 代码片段六: 即使
var
声明变量写在了块里,变量依旧可以在声明之前使用,存在变量提升的现象。
再来看看其他声明方式的效果
// let 声明变量
console.log(a);
let a = 1;
console.log(a);
// const 声明变量
const a = 1;
console.log(a);
以这两种方式声明,在声明之前调用变量会抛出 ReferenceError
异常,只有在声明之后调用不会异常,可见这两种方式是不存在变量提示的。
总结
var
和function
在作用域内 存在着变量提升。- 变量提升将影响变量声明,而不会影响其值的初始化,在赋值之前,值为
undefined
。 function
的变量提升能够使函数在声明前能够被调用。- 以
let
、const
这两种声明变量的方式不会造成变量提升。
三、var 变量声明
var
声明一个变量,可同时将其初始化为一个值,它是一个全局作用域的声明方式,也被函数作用域限制。但因其全局作用,以及提前声明的特性,容易造成变量的全局污染,造成意想不到的后果。
1、声明一个变量
// 声明一个变量
var a;
2、声明并初始化一个变量
// 声明并初始化一个变量
var a = 1;
3、声明并初始化两个个变量
// 声明并初始化两个个变量
var a = 1, b = 2;
4、多个变量的初始化
// 多个变量的初始化
var a;
function f()
var a = b = 1
f()
console.log(a) // 打印:undefined
console.log(b) // 打印:1
在函数里以var a = b = 值
的方式将变量a
和b
同时赋值为了1,这种操作等用于var a = 1; b = 1
。但调用函数后,函数外打印打印这两个值时能正确执行 且 值不相等。
- a、先来讲讲为什么说能正确执行,
b
变量只在函数中出现过,根据局部能调用全局作用域,全局不能调用局部作用域的特点,b
应该会抛出未定义的异常才对,但实际上并没有这样。这是因为在函数内部初始化变量b
的时候,并未指定声明符,那么JavaScript将变量提前以var
的方式进行了声明,而这个提升是全局的。 - b、 再来说说为什么
a != b
,其实很简单,在程序最开始就声明了变量var a
,而执行函数时并没有将a
的值修改为1,这是因为被函数作用域所限制,1这个值只在函数中生效。
5、意想不到的全局污染
for (var i = 1; i <= 10; i++)
// 延时一秒后执行
setTimeout(function ()
console.log(i); // 输出十次11
, 1000)
var
变量在使用循环时搭配定时器,会产生意想不到的效果,程序的目的是在一秒之后分别输出1-10的值,结果却是输出十次11。将 var
改成 let
则恢复正常。
var x = 1;
function func1()
var y = 2;
function func2()
x = 4;
y = 5
z = 6;
func2()
console.log(x, y, z) // 打印:4, 5, 6
func1()
console.log(x) // 打印:4
上述代码,x
、y
、z
打印的值各是多少呢?将x
、y
、z
分开来看。
- 对于
x
来说它是写在所有函数之前的全局变量,对x
的修改是全局的,x
的最后一次修改是在func2
函数里,那么x
的值到最后应该为4。 - 对于
y
来说,是在func1
函数中声明的,那么其作用域只在func1
函数中生效,y
的最后一次修改是在func2
函数里,那么y
的值到最后应该为5。 z
的值只出现过一次赋值,在此之前并没有任何的变量声明,在func2
函数中以z = 5
表达式赋值为5,其写法相同于var z = 5
,那么z
的值到最后应该为6。
6、可重复声明
// 重复声明
var a = 1;
var a = 2;
console.log(a) // 打印最后赋的值:2
// 循环重复声明
var x;
for (var i=1; i <= 5; i++)
var x = i;
console.log(x) // 打印最后赋的值:5
使用var声明变量,是可以重复声明的,这有个好处就是写起来比较灵活,不会抛出重复声明的异常。
四、let 变量声明
let 是块级作用域的本地变量。与 var
声明不同的是,let不允许重复声明同一个变量,将会抛出 SyntaxError
异常,但可以修改变量的值。
// 块级作用域
let a = 1;
console.log(a) // 打印:1
a = 2;
// let a = 3; // 抛出 SyntaxError
console.log(a) // 抛出异常 ReferenceError
以 let
声明的变量不存在变量提升,在变量初始化前访问该变量会抛出 ReferenceError
异常,自块开始到在初始化之前属于暂存死区。
// 不存在变量提升
console.log(a) // 抛出 ReferenceError
let a = 1;
console.log(b) // 抛出 ReferenceError
let b = 2;
使用 let
声明的变量能够解决 三、var 变量声明 ⇨ 5、意想不到的全局污染 中所提到的全局污染。
-
此时程序能正确输出我们所期望的值,1-10之间的数。
for (let i = 1; i <= 10; i++) // 延时一秒后执行 setTimeout(function () console.log(i); // 输出1-10 , 1000)
-
此时每个变量在各自的作用域里各司其职,河水不犯井水,对于我们编写代码来说不会出现一些意外的值。
let x = 1; function func1() let y = 2; function func2() let x = 4; let y = 5 let z = 6; console.log(x, y, z) // 打印:4, 5, 6 func2() console.log(x, y) // 打印:1 2 func1() console.log(x) // 打印:1
五、const 常量声明
const 是块级作用域的本地常量。与变量不同的是,常量不支持重复声明也不支持修改,若是存在修改行为则会抛出 TypeError
异常。
// 块级作用域
const BASE = "块级";
console.log(BASE) // 正常打印
// const BASE = "重复赋值" // 抛出 SyntaxError
// BASE = "修改"; // 抛出异常 TypeError
console.log(BASE) // 抛出异常 ReferenceError
常量名和其他声明方式一样,都可以大小写字母,但程序员之间会使用全大写进行命名,这是为了便于辨别常量类型,可以说是程序员之间的一种默契。
// 声明常量
const BASE = "常量名大写"
// 声明并初始化两个个变量
const BASE_NAME1 = 1, BASE_NAME2 = 2;
const
常量不存在变量提升,在常量初始化前访问该常量会抛出 ReferenceError
异常,自块开始到在初始化之前属于暂存死区。
// 不存在变量提升
console.log(a) // 抛出 ReferenceError
const a = 1;
console.log(b) // 抛出 ReferenceError
const b = 2;
对于性能来说,const
不允许重新赋值的,所以转换逻辑很简单,其潜在优化比较好。但是这种差异是细微的,几乎察觉不到,使用常量更多是注重代码风格,便于阅读。
六、var、let和const应用场景
声明 | 描述 | 作用域 | 是否存在变量提升 |
---|---|---|---|
var | 声明一个变量,可同时将其初始化为一个值 | 全局作用域 | ✅ |
let | 声明一个块级本地变量,可同时将其初始化为一个值 | [块级/局部]作用域 | ❎ |
const | 声明一个只读的命名常量 | [块级/局部]作用域 | ❎ |
- 如果一个变量在不会发生改变,在大多数情况下应使用
const
进行声明将其变为常量。这样有利于代码的阅读,不用考虑这个变量会不会发生改变,还能提高程序的 潜在 执行效率。 - 大部分情况下都不应该使用
var
进行声明,因其全局破坏的影响,尽量使用let
或const
进行取缔。 - 在使用 WebStorm 编辑器进行代码书写时,使用
var
进行声明会有明确的弱警告提示。
参考资料
推荐文章🍗
😝给笔者加个🍗
以上是关于JavaScript 各声明varletconst方式区别『详解』的主要内容,如果未能解决你的问题,请参考以下文章