前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >ES6语法:浅谈var、let和const

ES6语法:浅谈var、let和const

作者头像
用户9999906
发布2022-09-26 11:39:02
发布2022-09-26 11:39:02
36900
代码可运行
举报
文章被收录于专栏:学编程的GISer学编程的GISer
运行总次数:0
代码可运行

以下内容基于《JavaScript高级程序设计》这本书创作

公众号后台回复 js 可获得本书电子版

文章大纲

1.变量

变量可以保存任何类型的数据

有三个关键字可以声明变量:var、let、const,其中var在ECMAScirpt的所有版本中均可使用,而let和const只能在ES6及更晚的版本中可以使用

以下对var、let和const关键字进行对比:

(1)是否初始化变量

先说结论:var和let不会初始化,而const会初始化

证明:

1)var

代码语言:javascript
代码运行次数:0
运行
复制
var uname = 'dapan';
uname = 32;
console.log(uname);

这里,uname被定义为一个保存字符串值'dapan'的变量,var的初始化并不会将uname标识为字符串类型,只是一个简单的赋值而已,随后不仅可以改变保存的值,还可以改变值的类型。

2)let

代码语言:javascript
代码运行次数:0
运行
复制
let uname = 'dapan';
uname = 32;
console.log(uname);

这里,let声明的变量和var一样,可以改变值,也可以改变值的类型

3)const

代码语言:javascript
代码运行次数:0
运行
复制
const uname = 'dapan';
uname = 'Dapan';
console.log(uname);

报错:

这里,const声明变量时必须同时初始化变量,尝试修改const声明的变量会导致运行时报错

(2)声明的作用域

先说结论:var声明的作用域是函数作用域,let和const声明的作用域是块级作用域

证明:

1)var

代码语言:javascript
代码运行次数:0
运行
复制
function demo() {
  var city = 'guangzhou';
}
demo();
console.log(city);

报错:

这里,city变量是在函数demo()内部用var定义的,调用它会创建city变量,调用之后变量随即被销毁,故会报错

修改后:

代码语言:javascript
代码运行次数:0
运行
复制
function demo() {
  var city = 'guangzhou';
  console.log(city);
}
demo();

函数内部打印则不报错;

去掉var关键字:

代码语言:javascript
代码运行次数:0
运行
复制
function demo() {
  city = 'guangzhou';
}
demo();
console.log(city);

同样可以打印出来city的值,因为如果忽略var操作符,可以创建一个全局变量,那么只要调用一次demo()函数,就会定义city这个全局变量,并且可以在函数外部访问到(但是并不推荐省略var操作符定义全局变量)

2)let

先看函数作用域:

代码语言:javascript
代码运行次数:0
运行
复制
function demo() {
  let city = 'guangzhou';
}
demo();
console.log(city);

再看块级作用域:

代码语言:javascript
代码运行次数:0
运行
复制
if (true) {
  let city = 'guangzhou';
}
console.log(city);

报错:

修改为在块作用域里面打印:

代码语言:javascript
代码运行次数:0
运行
复制
if (true) {
  let city = 'guangzhou';
  console.log(city);
}

因为块作用域是函数作用域的子集,所以let在声明变量时,函数外边和块作用域外边都访问不到变量

3)const

const和let的作用域一样,简单看一下不再做解释:

代码语言:javascript
代码运行次数:0
运行
复制
function demo() {
  const city = 'guangzhou';
}
demo();
console.log(city);

代码语言:javascript
代码运行次数:0
运行
复制
if (true) {
  const city = 'guangzhou';
}
console.log(city);

均这个报错:

代码语言:javascript
代码运行次数:0
运行
复制
if (true) {
  const city = 'guangzhou';
  console.log(city);
}

正常打印:

(3)冗余声明是否报错

先说结论:var不会报错,let和const会报错:

1)var

代码语言:javascript
代码运行次数:0
运行
复制
var sex = 'boy'
var sex = 'girl'
console.log(sex);

2)let

代码语言:javascript
代码运行次数:0
运行
复制
let sex = 'boy'
let sex = 'girl'
console.log(sex);

但是在不同块作用域是可以重复声明的:

代码语言:javascript
代码运行次数:0
运行
复制
let sex = 'boy';
if (true) {
  let sex = 'girl';
  console.log(sex);
}
console.log(sex);

且对声明冗余报错不会因为混用var和let而受影响:

代码语言:javascript
代码运行次数:0
运行
复制
var sex 
let sex 

3)const

代码语言:javascript
代码运行次数:0
运行
复制
const sex 
const sex 

和let一样,const也允许在不同块作用域内重复声明变量,且混用var和const声明同样会报错

(4)是否会在作用域中提升变量

先说结论:var声明的变量会在作用域内提升变量,而let和const不会

1)var

代码语言:javascript
代码运行次数:0
运行
复制
console.log(age)
var age = 100

这里,并没有报错是因为var声明变量时把变量提升到了作用域的顶部,上边代码其实等价于下边这段代码:

代码语言:javascript
代码运行次数:0
运行
复制
var age;//提升了声明变量
console.log(age);
age = 100;

2)let

代码语言:javascript
代码运行次数:0
运行
复制
console.log(age);
let age = 100;

报错:

let和var的一个重要区别就是let声明的变量不会在作用域中被提升

3)const

和let关键字一样,不能被提升,不再赘述

(5)全局声明

与var关键字不同,使用let和const声明的变量不会成为window对象的属性(var变量则会)

证明 :

代码语言:javascript
代码运行次数:0
运行
复制
var x = 99;
console.log(window.x);
代码语言:javascript
代码运行次数:0
运行
复制
let x = 99;
console.log(window.x);

代码语言:javascript
代码运行次数:0
运行
复制
const x = 99;
console.log(window.x);

打印结果:

(6)for循环中的let声明

在let出现之前,for循环定义的迭代变量会渗透到循环体外部:

代码语言:javascript
代码运行次数:0
运行
复制
for (var i = 0; i < 5; i++) {
  //循环逻辑
}
console.log(i);

打印结果:

改成let之后这个问题就消失了:因为迭代变量的作用仅限于for循环块内部:

代码语言:javascript
代码运行次数:0
运行
复制
for (let i = 0; i < 5; i++) {
  //循环逻辑
}
console.log(i);

报错:

使用var时,最常见的问题就是对迭代变量的奇特声明和修改。判断下边代码的输出:

代码语言:javascript
代码运行次数:0
运行
复制
for (var i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(i);
  }, 0);
}

你可能以为输出的是0、1、2、3、4,但其实输出的是5、5、5、5、5,之所以会这样是因为在退出循环时,迭代变量保存的时导致循环退出的值:5。在之后执行超时逻辑时,所有的i都是同一个变量,因而输出的都是5。

而在使用let声明迭代变量时,JavaScript引擎在后台会为每个迭代循环声明一个新的迭代变量。每个setTimeout引用的都是不同的变量实例,所以console.log输出的是我们期望的值。

代码语言:javascript
代码运行次数:0
运行
复制
for (let i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(i);
  }, 0);
}

打印:

思考:上边这段代码能不能把let替换为const,为什么?

2. 声明风格及最佳实践

摘自《JavaScript高级程序设计》


可以的话,希望能够转发分享,点个在看并且点个~~也欢迎规范转载~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 学编程的GISer 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.变量
    • (1)是否初始化变量
    • (2)声明的作用域
    • (3)冗余声明是否报错
    • (4)是否会在作用域中提升变量
    • (5)全局声明
    • (6)for循环中的let声明
  • 2. 声明风格及最佳实践
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档