JavaScript变量中var,let和const的区别
作者:胖可丁 发布时间:2024-05-09 15:07:24
前言
JavaScript中一共有3种用来声明变量的关键字,分别是var、let和const。
其中var关键字是ES5时代的产物,由于ES5对变量的约束很宽松,使用var来声明变量时经常会出现一些预料之外的问题。 ES6为了使变量的定义更加规范,提出了let和const这两个关键字。
因此要解释清楚这三个的区别,首先要从ES5时代和ES6时代的差别说起,主要是var和let的区别。
ES5与ES6的区别
1. 作用域
使用不同的关键字来声明变量,主要就是对变量的作用域有不同的限制,因此var和let最主要的区别就是变量作用域的区别。
var声明的范围是函数作用域,函数体之外无法访问到函数体内声明的var变量。
做题的时候经常会有在全局和函数体内声明同名变量的场景,要知道不同作用域的变量是不会互相干扰的。
var a = 10;
function logA() {
var a = 20;
console.log(a); // 20
}
console.log(a); // 10
let声明的范围是块作用域,块作用域是函数作用域的子集,可以使用花括号
{...}
来限定块级作用域。
2. 全局属性
在全局作用域下使用var和let声明变量,变量都是会在页面的声明周期内存续。
但是使用var声明的变量会成为window对象的属性,使用let声明则不会。
3. 变量提升与暂时性死区
var声明存在变量提升的行为。
变量的声明、初始化和赋值被分为三步进行,对于var变量,声明和初始化会被提升到作用域的顶部。
也就是说,编译器在遇到var声明时,会先在作用域顶部声明一个var变量并将其初始化为undefined值。
因此在代码执行流遇到var声明语句之前访问var变量并不会报错,而是会访问到undefined值。
(function example() {
console.log(age); // undefined
var age = 20;
})();
// 相当于
(function example() {
var age;
console.log(age); // undefined
age = 20;
})();
ES6对先访问后声明变量的行为做了约束,因此let和const声明会存在TDZ暂时性死区。
即JavaScript引擎在编译时如果遇到let和const声明,会将它们放入暂时性死区以阻止访问,只有在执行到变量声明的语句后,才会将变量从TDZ中移出。
因此如果在变量声明语句之前访问变量,相当于企图访问TDZ中的变量,JavaScript会抛出运行时错误ReferenceError
。
ES5的变量提升和ES6的暂时性死区的区别还有一个“副作用”就是改变了
typeof
操作对于变量的访问性。已知在ES5时对于未声明变量唯一的安全操作是
typeof
,会返回undefined值。TDZ的出现导致即使使用
typeof
,也不能在let和const声明语句执行之前访问let和const变量,依然会报ReferenceError
。
4. 重复声明
var声明是允许重复的,可以重复使用var关键字来声明同名变量,后来声明的变量值会覆盖之前的值。
为了阻止重复声明变量这个容易让人迷惑的行为,ES6限制了let和const声明的变量都是不可重复的,如果重复声明会报
SyntaxError
错误。
这个限制不仅体现在let声明对let声明,如果想用let去重复声明var变量也是不被允许的。
let与const的区别
1. 常量
同样都是ES6的变量声明关键字,let和const的区别就在于使用const声明创建的是一个值的只读引用。
只读引用意味着对于原始值来说,const声明不可以再重新赋值;
对于引用值来说,const声明不可以再修改引用,但是可以修改对象的属性值或者数组内部的值。
最佳实践
尽量不使用var。因为let和const已经可以替代var的位置,满足开发需求,顺便还规避了很多不必要的问题。
优先使用const声明,let声明次之。const声明有点像保护变量的机制,它能预防和阻止预期之外的变量修改。 对于有修改需求的变量,就使用let声明。
来源:https://juejin.cn/post/7142061045660516360


猜你喜欢
- 一、装饰器的本质:装饰器(decorator)本质是函数闭包(function closure)的语法糖(Syntactic sugar)函
- JavaScript substr 方法substr 方法用于根据开始位置和长度截取字符串并返回截取部分字符串。其语法如下:str_obje
- 前言飞桨(PaddlePaddle)是集深度学习核心框架、工具组件和服务平台为一体的技术先进、功能完备的开源深度学习平台1. 任务描述乘坐出
- 如下所示:#!/usr/bin/env pythonimport osimport sysclass CConsole: M_MAP_COL
- 示例很简单,注释里也都做了说明,这里就不多废话了。<?php/*从平台获取数据库名*/$dbname = "";/
- 最近切换到了Ubuntu的系统作为工作环境, 在使用Pycharm的时候, 出现了个奇怪的问题中文是无法正常输入的, 然后找遍了网上的解决办
- /** * 递归法实现的快速排序 * @param $seq * @return array */f
- 本文实例讲述了Python实现的质因式分解算法。分享给大家供大家参考,具体如下:本来想实现一个其它的基本数学算法问题,但是发现在实现之前必须
- 使用场景一:如果在一张表中ManayTOManay字段关联的是自身,也就是出项这样的代码:ManyToManyField(self)那么,你
- 1、pylint是什么? Pylint 是一个 Python 代码分析工具,它分析 Python 代码中的错误,查找不符合代码风格标准(Py
- Oracle9i之前,中文是按照二进制编码进行排序的。在oracle9i中新增了按照拼音、部首、笔画排序功能。 1、
- 本文实例为大家分享了python微信跳一跳的具体代码,供大家参考,具体内容如下部分代码分享:wechat_jump.pyfrom __fut
- 准备工具pip3 install PILpip3 install opencv-pythonpip3 install numpy谷歌驱动建议
- server:#coding=utf-8from BaseHTTPServer import BaseHTTPRequestHandleri
- 两个并发事务同时访问数据库表相同的行时,可能存在以下三个问题:1、幻想读:事务T1读取一条指定where条件的语句,返回结果集。此时事务T2
- 前言python+mysql.connector,demo实战框架搭建说实话,其实没有使用到框架,只是用了, python+mysql.co
- 源自MySQL 5.7 官方手册 手册地址一、SELECT…INTO介绍SELECT…INTO用
- 随着网站访问量的加大,每次从数据库读取都是以效率作为代价的,很多用ACCESS作数据库的更会深有体会,静态页加在搜索时,也会被优先考虑。互联
- 一个是没有对输入的数据进行过滤(过滤输入),还有一个是没有对发送到数据库的数据进行转义(转义输出)。这两个重要的步骤缺一不可,需要同时加以特
- 前言python中进行面向对象编程,当在子类的实例中调用父类的属性时,由于子类的__init__方法重写了父类的__init__方法,如果在