详解JavaScript中var和let的区别
作者:掘金小逆 发布时间:2024-04-29 13:23:14
变量
ECMAScript变量是松散类型,意思就是说变量可以保存任何类型的数据,每个变量只不过是用于保存任意值的命名占位符。在JavaScript中,有3个关键字可以声明变量:var、const和let,其中var在ECMAScript的所有版本中都可以使用,而const和let只能在ECMAScript 6及更晚的版本中使用
var 关键字
如果我们想定义变量,我们可以使用var操作符(这里要注意var也是一个关键字~),后跟变量名
var message;
这行代码会定义一个名为message的变量,用于保存任何类型的值,如果在不初始化的情况下,默认为undefined。ECMAScript实现变量初始化,因此可以同时定义变量并且设置它的值
var message = "hi";
通过上方代码我们可以了解到,message被定义为一个保存字符串值hi的变量,像这样初始化变量不会将它标识为字符串类型,这仅仅是一个简单的赋值而已,我们不仅可以改变保存的值,同时还可以改变值的类型
var message = "hi"
message = 100 ;
通过上方代码我们可以看到,message首先被定义为一个用于保存字符串值hi的变量,然后又被重写为保存了数值100,虽然不推荐改变变量保存值的类型,但是这个在ECMAScript里面是非常有效的
var声明作用域
我们在定义一个函数变量的时候,通常都会考虑他们的作用域,使用var操作符定义的变量将会成为包含它的函数的局部变量,比如用var在一个函数内部定义一个变量,就意味着一旦出了这个区域,此定义无效
<script>
function test() {
var message = "hi";
}
test();
console.log(message);
</script>
从上方代码我们可以看到,message变量是在函数内部使用var定义的,函数名叫test() ,调用它会创建这个变量并且会给它赋值,调用结束之后这个变量就会被销毁,因此上方代码的倒数第二行会报语法错误,如果我们想要解决这个问题,把message定义成全局变量即可
<script>
function test() {
message = "hi";
}
test();
console.log(message);
</script>
去掉之前的var操作符之后,message就变成了全局变量,我们只需要调用一次函数test() ,就可以定义这个变量,并且在函数外部访问
注意注意!!!
我们虽然可以通过省略var操作符来定义全局变量,但是不推荐这么做,在局部作用域中定义的全局变量很难去维护,也会给我们造成一定的困惑,因为我们不能确定这个var是不是有意而为之,如果像这样给未声明的变量赋值,则会导致抛出ReferenceError
如果我们需要定义多个变量,我们可以在一条语句中用逗号分隔每个变量(及可选的初始化)
<script>
var message = "hi";
found = false;
age = 29;
</script>
这里我们定义了3个初始化变量,因为ECMAScript是松散类型的,所以使用不同数据类型初始化的变量可以用一条语句来声明,插入换行和空格缩进不是必需品(因为这里不是Python~)
小tip
在严格模式下,不能定义名为eval和arguments的变量,否则会导致语法错误
var声明提升
我们在使用var的时候,下面的代码不会报错,因为使用这个关键字声明的变量会自动提升到函数作用域的顶部
<script>
function foo() {
console.log(age);
var age = 26;
}
foo();
</script>
之所以这个代码不会报错,是因为ECMAScript已经帮我们解决啦~(它自己会自动调整阅读顺序),这就是所谓的提升,也就数把所有变量声明都拉到函数作用域的顶部,此外,反复多次使用var声明同一个变量也是没有问题的
let声明
let跟var的作用差不多,但是有着十分重要的区别,最明显的区别就是,let声明的范围是块作用域,而var声明的范围是函数作用域
<script>
if(true){
var name = "Matt"
console.log(name); //Matt
}
console.log(name); //Matt
if(true){
let age = 26 ;
console.log(age) //26
}
console.log(age) //ReferenceError
</script>
在这里,age变量之所以不能在if块外部被引用,是因为它的作用域仅限于该块内部,块作用域是函数作用于的子集,因此适用于var的作用域也适用于let
let也不允许同一个块作用域中出现冗余声明,这也会报错
var name ;
var name ;
let age ;
let age ; //SyntaxError 标识符age已经声明过了
当然,JavaScript引擎会记录用于变量声明的标识符及其所在的块作用域,因此嵌套相同的标识符不会报错, 这是因为在同一个块中没有重复声明
<script>
var name = "Nicholas";
console.log(name); // Nicholas
if (true) {
var name = "Matt";
console.log(name); // Matt
}
let age = 30;
console.log(age); // 30
if (true) {
let age = 26;
console.log(age); // 26
}
</script>
对声明冗余报错不会因混用let和var而受影响,这两个关键字声明的并不是不同类型的变量,它们只是指出变量在相关作用域如何存在
var name ;
let name ; //SyntaxError
let age ;
var age ; //SynatxError
来源:https://juejin.cn/post/7150109407819825159
猜你喜欢
- 6月初,Python之父Guido van Rossum在今天的PyCon US大会上作了名为“Python Language”的演讲。近日
- 如下所示:希望可以从对admin提交的密码加密,并验证电话号码均为数字。查看admin.pyfrom django.contrib impo
- 在头条看了一篇文章,说五行代码实现人脸识别,一时感兴趣了,来搞搞先是按照文章说的 操作了几步,到后面虽然,import dlib 不报错,但
- 本文旨在讲述 RPC 框架设计中的几个核心问题及其解决方法,并基于 Golang 反射技术,构建了一个简易的 RPC 框架。项目地址:Tin
- 将电话簿TeleAddressBook.txt和电子邮件EmailAddressBook.txt合并为一个完整的AddressBook.tx
- 起序:本文是在 python 自己的虚拟环境下做的,不是在 Anaconda 下做的。一、安装想要更改 jupyterlab 的默认启动位置
- 编号标准宗地编码(landCode)所在区段编码(sectCode)1131001BG001G0012131001BG002G0013131
- 新安装的MySQL5.7,登录时提示密码错误,安装的时候并没有更改密码,后来通过免密码登录的方式更改密码,输入update mysql.us
- 分页,就是按照某种规则显示分组数据集,但是在SQL Server 中,分页并不是十分容易就能够实现。在过去,开发人员通常需要自己编写程序,使
- <% SoFia_DbName="jiaoyou&qu
- 先来看看什么是书签查找: 当优化器所选择的非聚簇索引只包含查询请求的一部分字段时,就需要一个查找(lookup)来检索其他字段来满足请求。对
- 有时候很多朋友访问自己的asp或php等程序页面时出现一些错误,就是页面无法显示也没有详细的错误信息,就算iis中开启了显示详细的错误也不能
- Python 用了好长一段时间了,起初是基于对爬虫的兴趣而接触到的。随着不断的深入,慢慢的转了其它语言,毕竟工作机会真的太少了。很多技能长时
- 快速排序(QuickSort)是对冒泡排序的一种改进:基本思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一
- 本文实例讲述了JS实现基于Sketch.js模拟成群游动的蝌蚪运动动画效果。分享给大家供大家参考,具体如下:基于Sketch.js,实现了物
- 前言相信大家都知道当声明一个变量,并且没有给赋值的情况下,它的初始值是undefined。但是在javascript中,怎么检查一个值是否为
- 看到豆瓣上有网友提了这个问题,看到回答的人不多,忍不住写了下面的内容。工作中最常用到的统计方法有哪些?根据我自己的经验给举些例子。1.通过一
- 文件拆分代码:#-*-encoding:utf-8-*-import osimport sysimport threadingdef get
- 在Centos中安装完MySQL数据库以后,不知道密码,这可怎么办,下面给大家说一下怎么重置密码1、修改配置文件my.cnf 按i编辑[ro
- 一,将介绍如何(1)mysql5.7是有默认密码的查找默认密码grep 'temporary password' /var/