在JavaScript开发中,关于var、let和const你需要知道这些


📋前言

计算机编程中最基本的一个就是使用名字(或标识符)表示值。绑定名字和值为我们提供了一种引用值和在程序中使用值的方式,对于绑定名字和值,我们通常会说把值赋给变量。术语“变量”意味着可以为其赋予新值,也就是说与变量关联的值在程序运行时可能发生变化。如果把一个值永久地赋予给一个名字。那么可以称该名字为常量而不是变量。(来自犀牛书变量声明与赋值)

在 JavaScript 中使用变量或常量前,必须先声明它。在 ES6 之前,我们是通过 var 关键字来声明变量的,在ES6之后,我们可以通过 letconst 关键字来完成声明。


🎯var

1️⃣ var 是 JavaScript 早期版本中最常见的变量声明方式,它可以在全局作用域和函数作用域中使用。使用 var 声明的变量具备变量提升的特性,但是在没有赋值的情况下,其默认值为 undefined。

📝我们看下面这段代码,会输出什么呢?没错输出的是 undefined。

function getNumber(isNumber) {
  if (isNumber) {
    var num = "7";
  } else {
    var notNum = "not number!";
    console.log(num);
  }
}
getNumber(false);

在这里插入图片描述
因为在 JavaScript 中有一个提升机制,就是无论你在哪里使用 var 关键字声明变量,它都会被提升到当前作用域的顶部。在运行 getNumber 函数时,实际上执行结构是下面这个样子。

function getNumber(isNumber) {
  var num;
  var notNum;
  if (isNumber) {
    num = "7";
  } else {
    notNum = "not number!";
    console.log(num);
  }
}
getNumber(false);

因为在开头定义变量时,没有给 num 变量赋任何值,并且 getNumber 传入的是 false,导致 if 语句未执行,num 未被赋值,所以控制台输出 undefined。

2️⃣ var 声明的变量可以被重复定义,这意味着可以在同一作用域内多次声明同一个变量,而不会报错。但是,如果 var 定义的变量在全局作用域中声明,则有可能会覆盖掉某些全局变量,造成不必要的麻烦。

📝如下面这段代码就很麻烦了,会造成环境卡死。

function Sum(arrList) {
  var sum = 0;
  for (var i = 0; i < arrList.length; i++) {
    var arr = arrList[i];
    for (var i = 0; i < arr.length; i++) {
      sum += arr[i];
    }
  }
  return sum;
}
var arr = [1, 2, 3, 4, 5];
document.write(Sum(arr));

这是因为在两层 for 循环中我们使用同一变量 i 进行赋值时,代码在执行过程中,第二层的 for 循环会覆盖外层变量 i 的值。

3️⃣ 由于 var 存在变量提升的问题,所以它有可能会引起一些奇怪的问题。比如,在循环体内使用 var 定义的变量(如上述代码),可能会因为变量提升而影响到其他的循环体。

📝补充:使用 var 关键字定义的变量只有两种作用域,全局作用域和函数作用域,两者均不是块结构,会造成变量声明的提升。这可能出现下面这种问题:

function func() {
  for (var i = 0; i < 5; i++) {}
  console.log(i); // 5
}
func();

在这里插入图片描述
运行上述代码后,你会发现页面上会显示 5。我们虽然是在 for 循环中定义的 i 变量,但由于变量被提升到 for 语句之上,所以退出循环后,变量 i 并没有被销毁,我们能够在循环外获取它的值。


🎯let

1️⃣let 是 ES6 中新增的一种变量声明方式,它主要用于声明块级作用域中的变量。使用 let 声明的变量不存在变量提升的问题,因此不能在声明之前使用变量。let 声明的变量不能被重复定义,如果在同一个作用域内多次声明同一个变量,会报错。

📝我们看下面这段代码会输出什么呢?

function getNumber(isNumber) {
  if (isNumber) {
    let num = "7";
  } else {
    let notNum = "not number!";
    console.log(num);
  }
}
getNumber(false);

在这里插入图片描述
ReferenceError 是一个引用类型的错误,num is not defined 意思是 num 变量并不存在。

let 关键字声明变量,其作用域是一个块,如果我们是在花括号 {} 里面声明变量,那么变量会陷入暂时性死区,也就是在声明之前,变量不可以被使用。

在上面代码中,我们的 num 变量是放在 if(){} 这个块中,并没有在 else{} 块中,所以会形成暂时性死区。
在这里插入图片描述
虽然 let 关键字声明的变量可以重新赋值,但是它与 var 关键字有所不同,let 关键字不能在同一作用域内重新声明,而 var 可以。

let i = 5;
let i = 6;
console.log(i);

可以看到控制台会报参数错误(SyntaxError)。
在这里插入图片描述
如果将上面代码中的 let 关键字改为 var 关键字便不会报错了。

var i = 5;
var i = 6;
console.log(i);

在这里插入图片描述

2️⃣ let 声明的变量具备块级作用域,这意味着它们只在相应的代码块中存在,超出该块范围时就会被销毁。在循环体内使用 let 定义变量,则可以避免使用 var 带来的问题。

function func() {
  for (let i = 0; i < 5; i++) {}
  console.log(i);
}
func();

在这里插入图片描述
你会发现,控制台报错了。这是因为上面代码中的 i 变量只存在于 for 循环这个块中,当循环结束,i 变量就被销毁了,所以在 for 循环外访问不到。(对比看 🎯var 的3️⃣的补充)


🎯const

1️⃣ const 也是 ES6 中新增的一种变量声明方式,它用于声明常量。使用 const 声明的变量必须进行初始化操作,不能在声明后再次赋值。这意味着,const 声明的变量值是不可变的,不能被重新赋值。(除了不能被重新赋值之外,const 声明的变量与 let 声明的变量类似,也具备块级作用域。)

📝例如:

❗❗❗const 声明的变量值是不可变的,不能被重新赋值。否则会报如下错误。

const MaxAge = 100;
MaxAge = 10;
console.log(MaxAge);

在这里插入图片描述

❗❗❗声明的变量必须进行初始化操作,不能在声明后再次赋值。否则会报如下错误。

const Num;
console.log(Num);

在这里插入图片描述

2️⃣ const 声明的变量不是真正的常量,而是指向内存地址的指针。因此,如果 const 声明的变量是对象或数组,虽然无法重新赋值,但是可以更改其属性或元素值。

📝值类型是指变量直接存储的数据,例如:

const num = 23;

这里 num 变量就是值类型,我们使用的是 const 关键字来定义 num,故赋予变量 num 的值 20 是不可改变的。

引用类型是指变量存储数据的引用,而数据是放在数据堆中,比如,用 const 声明一个数组。

const arr = ["一", "二", "三"];

如果你尝试去修改数组,同样会❗报错。

const arr = ["一", "二", "三"];
arr = ["五", "六", "七"];

在这里插入图片描述

但是,使用 const 关键字定义的引用类型还是可以通过数组下标去修改值 。例如:

const arr = ["一", "二", "三"];
arr[0] = "四";
arr[1] = "五";
arr[2] = "六";

console.log(arr);

在这里插入图片描述

因为变量 arr 保存的是数组的引用,并不是数组中的值,只要引用的地址不发生改变就不会保错。这就相当于一个房子,它拥有固定的位置,但住在房子里的人不一定固定。
在这里插入图片描述


🎯相关面试题

  • 请分别描述 var、let 和 const 的特点和使用场景?
  • 请解释 JavaScript 中的变量提升?var、let 和 const 是否存在变量提升?
  • 在函数内部,使用 var 和 let 声明的变量有什么区别?
  • const 声明一个对象时,可以修改对象的某些属性值,那么请问这是不符合 const 的定义吗?
  • 在循环语句中,使用 let 声明的变量与使用 var 声明的变量有什么区别?
  • 请列举出在 JavaScript 中 var 和 let 的最大区别?
  • 请列举出在 JavaScript 中使用 const 的原因?
  • 请写一个函数,该函数接受两个形参并返回它们的和,使用 const 关键字来声明变量。
  • 请解释 const 声明的数组中 push 操作的效果?并使用代码进行演示。
  • 请列举出只能使用 let 或 const 声明而不能使用 var 声明的情况?

📝总结

varletconst 是 JavaScript 中的三种变量声明方式,主要区别如下:

  • 变量作用范围不同var 声明的变量作用域为函数作用域(全局作用域),letconst 声明的变量作用域为块级作用域(在花括号 {} 内)。

  • 变量是否可以重复声明var 可以被重复声明,后面的声明会覆盖前面的声明;而 letconst 同一作用域内不允许重复声明相同名称的变量。

  • 变量初始化和赋值方式不同var 不需要进行初始化,定义时如果没有赋值会自动赋值为 undefined;letconst 声明时必须赋初值或者等待第一次被赋值。同时,const 声明的变量是一个常量,不允许改变其值。而 varlet 声明的变量可以被重新赋值。

  • 变量提升方式不同var 变量会存在变量提升,即在变量声明前使用该变量会得到 undefined,因为该变量已经被声明了;而 letconst 声明的变量不存在变量提升,必须在声明后才能使用。

使用场景:在实际开发中,可以根据具体需求来选择使用 varletconst,一般建议优先使用 const 声明常量,let 声明变量的情况下可以在需要修改变量值时使用,而 var 声明变量则可以在需要全局共享变量时使用。
在这里插入图片描述

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黛琳ghz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值