【JavaScript】你从未如此了解const、let与var

2023-11-01

在这里插入图片描述

引言

ES2015(ES6)推出了许多闪亮的新功能。而letconst却是其中非常亮眼的功能,可用于变量声明。那么它们与var有和不同呢?

内容速递

看了本文您能了解到的知识!

在本文中,我们将讨论varletconst的作用域、用途和变量提升。了解它们的异同,熟练掌握它们的使用。

1、var

ES6出现之前,必须使用var声明。但是var声明的变量引出了很多前端的问题。这也是为什么必须要有新的方法来声明变量。

1.1、var的作用域

JavaScript中,var关键字声明的变量是函数作用域或全局作用域的变量,它的作用域在声明的函数内部或全局范围内。如果在函数外部使用var声明变量,则该变量会成为全局变量。

在函数作用域中,var声明的变量只在声明的函数内部有效,函数内部的变量不会影响函数外部的变量。如果在函数内部重新声明一个同名变量,将会覆盖函数外部的同名变量。

例如

var x = 1;

function test() {
  var x = 2;
  console.log(x); // 输出2
}

test();
console.log(x); // 输出1

以上代码中,x是全局变量,在test函数内部重新声明了一个同名变量x,该变量只在test函数内部有效,不会影响函数外部的变量x

如果在函数内部没有使用var关键字声明变量,而直接使用变量名赋值,相当于在全局作用域中创建了一个变量。

例如

function test() {
  x = 1;
}

test();
console.log(x); // 输出1

以上代码中,在test函数内部没有使用var关键字声明变量x,而直接给x赋值。这相当于在全局作用域中创建了一个变量x,可以在函数外部访问到该变量。

需要注意的是,使用var关键字声明变量时,如果没有使用var关键字直接给变量赋值,会创建一个全局变量,这是一个常见的错误,应该避免。为了避免这种错误,可以使用"use strict"严格模式。在严格模式下,如果没有使用var关键字声明变量,JavaScript会抛出ReferenceError异常。

例如

"use strict";

function test() {
  x = 1; // 抛出ReferenceError异常
}

test();
console.log(x);

1.2、var变量可以重新声明和修改

JavaScript中,使用var关键字声明的变量是可以重新声明和修改的。这是因为var关键字声明的变量是函数作用域或全局作用域的变量,它的作用域在声明的函数内部或全局范围内。

在同一个作用域内,如果使用var关键字重新声明一个已经存在的变量,不会报错,而是会覆盖之前的变量声明。

例如

var x = 1;
var x = 2;
console.log(x); // 输出2

以上代码中,先使用var关键字声明一个变量x并赋值为1,然后再次使用var关键字声明同名变量x并赋值为2,这会覆盖之前的变量声明,最终输出的结果为2

在同一个作用域内,如果直接修改一个变量的值,不会报错,而是会修改变量的值。

例如

var x = 1;
x = 2;
console.log(x); // 输出2

以上代码中,先使用var关键字声明一个变量x并赋值为1,然后直接修改变量x的值为2,最终输出的结果为2

1.3、var的变量提升

JavaScript中,使用var关键字声明的变量具有变量提升(Hoisting)的特性。变量提升是指在当前作用域内,变量声明会被提升到作用域的顶部,因此可以在变量声明之前使用变量。

例如

console.log(x); // 输出undefined
var x = 1;

以上代码中,先输出变量x的值,由于变量提升的特性,变量x的声明被提升到作用域的顶部,因此可以在变量声明之前访问变量x,输出结果为undefined

需要注意的是,只有变量声明被提升,变量赋值不会被提升

例如

console.log(x); // 输出undefined
var x = 1;
console.log(x); // 输出1

以上代码中,先输出变量x的值,由于变量提升的特性,变量x的声明被提升到作用域的顶部,变量赋值不会被提升,因此第一次输出结果为undefined,第二次输出结果为1

在函数作用域中,变量提升的特性也适用。

例如

function test() {
  console.log(x); // 输出undefined
  var x = 1;
  console.log(x); // 输出1
}

test();

以上代码中,在test函数内部使用var关键字声明变量x,并在变量声明之前输出变量x的值,由于变量提升的特性,变量x的声明被提升到函数作用域的顶部,因此可以在变量声明之前访问变量x,输出结果为undefined

1.4、var的问题

var关键字在JavaScript中存在一些问题,主要包括以下几点:

  1. 变量提升问题:使用var关键字声明的变量具有变量提升的特性,变量声明会被提升到作用域的顶部,因此可以在变量声明之前访问变量。这种特性可能会导致代码可读性和可维护性的问题,因为变量的声明位置与变量的使用位置不一致,会使代码难以理解和维护。
  2. 全局变量问题:如果在函数内部使用var关键字声明变量时,忘记使用var关键字或者错误地使用var关键字声明变量,会导致该变量成为全局变量,影响代码的可维护性和可靠性。
  3. 可重复声明问题:使用var关键字声明的变量可以在同一作用域内重复声明,这可能会引起命名冲突和变量覆盖的问题。
  4. 没有块级作用域:使用var关键字声明的变量只具有函数作用域和全局作用域,没有块级作用域。这意味着在块级作用域内声明的变量会泄漏到外部作用域,可能会引起命名冲突和变量覆盖的问题。

2、let

let现在已经成为变量声明的首选。这并不奇怪,因为它是对var声明的改进。

2.1、let的块级作用域

JavaScript中,使用let关键字声明的变量具有块级作用域的特性。块级作用域是指变量在指定的块内可见,而在块外不可见。块级作用域可以是函数、if语句、for语句等代码块。

例如

function test() {
  if (true) {
    let x = 1;
    console.log(x); // 输出1
  }
  console.log(x); // 抛出ReferenceError异常
}

test();

以上代码中,在if语句的代码块中使用let关键字声明变量x,并赋值为1,这个变量只在if语句的代码块中有效。在if语句的代码块外部访问变量x会抛出ReferenceError异常。

2.2、let可以被修改但是不能被重新声明

使用let关键字声明的变量可以被修改但不能重复声明,这是因为变量在块级作用域中具有唯一性

例如

let x = 1;
let x = 2; // 抛出SyntaxError异常

以上代码中,先使用let关键字声明变量x并赋值为1,然后在同一作用域内再次使用let关键字声明同名变量x并赋值为2,这会抛出SyntaxError异常。

需要注意的是,使用let关键字声明的变量在同一作用域内不能重复声明,但可以在不同作用域内声明同名变量。

例如

let x = 1;
if (true) {
  let x = 2;
  console.log(x); // 输出2
}
console.log(x); // 输出1

以上代码中,在全局作用域中声明变量x并赋值为1,然后在if语句的代码块中使用let关键字声明同名变量x并赋值为2,这不会影响全局变量x的值。在if语句的代码块外部,输出变量x的值为1

2.3、let的变量提升

就像var一样,let声明也被提升到作用域顶部。但不同的是:

  • var声明的变量会被提升到其作用域的顶部,并使用undefined值对其进行初始化。
  • let声明的变量会被提升到其作用域的顶部,不会对值进行初始化

因此,如果你尝试在声明前使用let变量,则会收到Reference Error。这是因为let关键字声明的变量具有暂时性死区(TDZ)的特性。暂时性死区是指在当前作用域内,变量从声明到初始化之前无法访问的区域

例如

if (true) {
  console.log(x); // 抛出ReferenceError异常
  let x = 1;
}

以上代码中,在if语句的代码块中先输出变量x的值,由于变量x还没有被声明和初始化,因此会抛出ReferenceError异常。

3、const

const声明的变量保持常量值。

3.1、const的块级作用域

JavaScript中,使用const关键字声明的变量同样具有块级作用域的特性,与let关键字类似。使用const关键字声明的变量也只在指定的块内可见,而在块外不可见。

例如

function test() {
  if (true) {
    const x = 1;
    console.log(x); // 输出1
  }
  console.log(x); // 抛出ReferenceError异常
}

test();

以上代码中,在if语句的代码块中使用const关键字声明变量x,并赋值为1,这个变量只在if语句的代码块中有效。在if语句的代码块外部访问变量x会抛出ReferenceError异常。

3.2、const不能被修改并且不能被重新声明

需要注意的是,使用const关键字声明的变量必须在声明时进行初始化并且初始化后不能再修改变量的值。这是因为const关键字声明的变量是常量,一旦初始化,它的值就不能再被修改。

例如

const x = 1;
x = 2; // 抛出TypeError异常

以上代码中,先使用const关键字声明常量x并赋值为1,然后在同一作用域内尝试修改常量x的值为2,这会抛出TypeError异常。

需要注意的是,使用const关键字声明的变量不能被重新赋值,但是它所引用的对象或数组等复合数据类型的属性或元素是可以被修改的。

例如

const arr = [1, 2, 3];
arr.push(4);
console.log(arr); // 输出[1, 2, 3, 4]

以上代码中,使用const关键字声明常量arr并赋值为数组[1, 2, 3],然后向数组中添加元素4,这不会抛出TypeError异常,因为常量arr所引用的数组本身并没有被重新赋值,只是修改了数组的元素。

在使用const关键字声明复合数据类型的变量时,需要注意变量所引用的对象或数组等是否会被修改。如果需要保证变量所引用的对象或数组等不被修改,可以使用Object.freeze()方法或其他的不可变数据类型来实现。

3.3、const的变量提升

就像let一样,const声明也被提升到顶部,但是没有初始化。使用const关键字声明的变量也具有暂时性死区(TDZ)的特性,与let关键字类似。在当前作用域内,变量从声明到初始化之前无法访问的区域。

4、const、let与var的区别

JavaScript中,constletvar都是用于声明变量的关键字,它们之间有以下几个方面的区别:

  1. 块级作用域constlet关键字都是块级作用域,而var关键字是函数作用域。
  2. 变量提升var关键字具有变量提升的特性,而constlet关键字不具有变量提升的特性。在使用var关键字声明变量时,变量声明会被提升到作用域顶部,因此可以在变量声明之前访问变量;而在使用constlet关键字声明变量时,访问未声明和未初始化的变量会抛出ReferenceError异常。
  3. 重复声明:使用var关键字声明的变量可以在同一作用域内重复声明,而使用constlet关键字声明的变量在同一作用域内不能重复声明。
  4. 赋值:使用const关键字声明的变量必须在声明时进行初始化,并且初始化后不能再修改变量的值;而使用let关键字声明的变量可以在声明后重新赋值。

博客说明与致谢

文章所涉及的部分资料来自互联网整理,其中包含自己个人的总结和看法,分享的目的在于共建社区和巩固自己。

引用的资料如有侵权,请联系本人删除!

感谢勤劳的自己个人博客GitHub,公众号【归子莫】,小程序【子莫说】

如果你感觉对你有帮助的话,不妨给我点赞鼓励一下,好文记得收藏哟!

幸好我在,感谢你来!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【JavaScript】你从未如此了解const、let与var 的相关文章

  • Dimple.js - 将数据标签添加到条形图的每个条形

    我使用的是dimple js 它基于d3 js 是否可以向本示例中提到的条形图的每个条形添加数据标签http dimplejs org examples viewer html id bars vertical http dimplejs
  • Javascript:如何检查异步操作是否仍在挂起/正在进行中?

    我想知道是否可以以某种方式检查 Javascript 中的异步操作是否仍处于待处理状态 因为我正在执行调用特定 URL 的数据库请求 虽然 db 调用仍在进行中 但我想停止任何其他传入的 db 调用 这意味着 停止对该 URL 的任何进一步
  • 在 Meteor.method 中调用函数返回未定义

    过去几天我一直在尝试从 Meteor 方法获取返回对象 每次我这样做我都会得到undefined在客户端上 Meteor methods CORSTest function let url www theverge com 2017 4 1
  • 使用 javascript 调用 ViewComponent

    我有一个带有几个视图组件的网页 当我单击这些组件时 我会为其打开一个简单的编辑器 请参见下图 如果我编辑文本并按 Enter 键 我想重新渲染视图组件而不是孔页面 是否可以使用 javascript 调用视图组件来获得此行为 通过更新 您现
  • browserify 错误 /usr/bin/env: 节点: 没有这样的文件或目录

    我通过 apt get install 安装了 node js 和 npm 以及所有依赖项 然后安装了 browserify npm install browserify g 它完成了整个过程 看起来安装正确 但是当我尝试为此做一个简单的捆
  • 允许指针(单击)事件穿过元素,同时保持滚动功能

    我的目标是拥有一个允许 下面要点击 交互的元素 滚动 众所周知 1 的解是pointer events none 这正如中所描述的单击 DIV 到底层元素 https stackoverflow com questions 3680429
  • 如何在CKEditor 5中监听焦点事件

    我想听一下 CKEditor 5 中的焦点事件 我认为这样的事情会起作用 但回调从未被调用 document querySelector editable ClassicEditor create el then editor gt edi
  • 从 DOM 中删除后,动态添加的 JavaScript 脚本会继续执行

    因此 我正在创建一个 SPA 并使用 AJAX 将 HTML 页面加载到我网站的索引页面中 问题是 当包含我的一个页面时 它似乎会徘 徊并执行其中的 JavaScript 代码 即使它随后从 DOM 中删除 索引 html 正文 div d
  • 使用 easyXDM 调整 IFrame 大小

    我将 iFrame 代码提供给客户 以便他们可以显示我网站上的动态内容 我希望其页面上的 iFrame 能够调整大小以适合我的内容 我按照 easyXDM 网站的说明进行操作 但也许我遗漏了一些东西 我没有收到任何错误 但 iFrame 保
  • t /= d 是什么意思? Python 和错误

    t current time b begInnIng value c change In value d duration def easeOutQuad swing function x t b c d alert jQuery easi
  • Web浏览器控件:如何捕获文档事件?

    我正在使用 WPF 的 WebBrowser 控件加载一个简单的网页 在这个页面上我有一个锚点或一个按钮 我想在我的应用程序后面的代码中 即在 C 中 捕获该按钮的单击事件 WebBrowser 控件是否有办法捕获加载页面元素上的单击事件
  • 比较 javascript 元素和 scala 变量的 Play 框架 Twirl 模板

    如下面的代码示例所示 我想比较 scala 辅助元素内的 javascript 元素 然而 即使存在元素 abcde 它也始终返回 false 除了使用标签之外 如何获取 scala 辅助元素内的 javascript 值 appSeq S
  • 如何为 ng-repeat orderBy 创建回调?

    寻找一种方法让 AngularJS 的 ng repeat orderBy 过滤器在完成渲染后执行回调 Markup div table thead tr th Name th th Age th tr thead tbody tr tr
  • 单击react.js 切换列表的背景颜色

    我正在尝试创建一个具有以下功能的列表 悬停时更改列表项的背景颜色 单击时更改列表项的背景颜色 在单击的元素之间切换背景颜色 即列表中只有一个元素可以具有 clicked 属性 我已经执行了 onhover 1 和 2 功能 但无法实现第三个
  • 在 中动态添加链接样式表 [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 如何将链接
  • 盒式捆绑包与 MVC4 捆绑包

    我目前正在开发一个原型 ASP NET MVC 3 解决方案 该解决方案将用作多个项目重写的基础 来自 Web 表单 我的目标之一是跨应用程序实现一些脚本管理 而不是我们目前没有的目标 MVC 3有一个缺陷恕我直言 如果您需要在部分视图或模
  • 使用 JavaScript 从 URL 变量读取来加载不同的 CSS 样式表

    我试图在我的 WordPress 博客上使用两个不同的样式表 以便在通过 Web 访问页面时使用一个样式表 而在通过我们的 iOS 应用程序访问博客内容时使用另一个样式表 现在 我们将 app true 附加到来自 iOS 应用程序的 UR
  • 地址更改时如何停止 Angular 重新加载

    我正在使用 Angular 的scrollTo and anchorScroll像这样 app controller TestCtrl function scope location anchorScroll scope scrollTo
  • 如何仅在第一次访问时弹出模态窗口

    我有一个模式窗口 当您访问某个页面时会弹出 访客必须选择我同意或我不同意 我需要一个漂亮的小 jquery 脚本 它会记住谁之前访问过该页面并同意 这样他们每次访问该页面时就不会弹出模式 有人可以推荐一个好的脚本来使用吗 这是代码 div
  • Angular 5 中 Observable.ForkJoin 的重复 Http 请求

    我有一个 Angular 5 应用程序 组件中包含以下代码 ngOnInit Observable forkJoin this highlightedInsight this insightService getHighlightedIns

随机推荐