资讯专栏INFORMATION COLUMN

JS中let与const命令如何使用

3403771864 / 268人阅读

  本篇文章主要讲述JS中let与const命令使用,通过代码展示给各位。

  let命令

  基本使用

  在ES6中,let命令是新增的声明变量,与var的差异在于let无法重复声明,且let有效只是在其命令的代码块内,let禁止变量出现变量提升现象,let的特点就是通过暂时性死区的方式来避免程序上的错误

  代码块:使用{}包括起来的内容

  声明变量:分配一个存储空间

  不可重复声明:let声明过后的变量无法再再次声明,而var可以重复声明

  {
  let a = 10;
  var a = 1; // 'a' has already been declared
  }


 

 {
  var a = 10
  var a = 1
  }
  console.log(a) // 1

  不同代码块可被重复声明:我们知道let的不可重复声明是作用在同一代码块中的,在后续中我们会具体解释相关的概念即块级作用域

  {
  let a = 1
  console.log(a)
  }
  {
  let a = 2
  console.log(a)
  }

  有效区间的不同:上述中,我们知道let只在其命令的代码块内有效,而var声明的变量可全局有效,现在举例为大家说明。

  {
  let a = 10;
  var b = 1;
  }
  console.log(a) // a is not defined
  console.log(b) // 1

  变量提升:我们熟悉在声明前调用为undefined,之前使用var声明变量,ndefined就是我们熟悉的声明但未赋值,这种现象叫做变量提升,可let禁止执行,因此,要想使用let所声明的变量,就要安排在声明后使用。

  console.log(bar) // Cannot access 'bar' before initialization
  let bar = 2

  变量提升的编译:现在看看变量提升现象在编译后的情况,更有利于了解变量提升现象出现的原因,所有的声明变量语句在编译后都会将声明语句提到程序的最先级,所以才会出现声明但未赋值的现象。

  // 编译前
  console.log(a)
  var a = '猪痞恶霸'
  // 编译后
  var a
  console.log(a)
  a = '猪痞恶霸'

  暂时性死区:在代码块中使用let声明变量前,该变量不可用,这种现象称为暂时性死区,其实这点和变量提升有些相似,我理解为:let禁止变量提升现象的原因是在声明变量前的代码区域为暂时性死区

  {
  // 暂时性死区
  tmp = 'abc';
  console.log(tmp)
  // 暂时性死区
  let tmp; // 声明tmp,结束暂时性死区
  console.log(tmp) // undefined 声明未赋值
  tmp = '123'
  console.log(tmp) // 123
  }

  隐蔽的死区:有些暂时性死区会在我们注意不到的地方,比如

  function bar(x = y, y = 2) {
  return [x,y]
  }
  bar() // Cannot access 'y' before initialization
  bar(2) // 无错误

  由于x的默认值为y,且y的声明还没开始,所以x = y处于死区中

  适用场景

  let与var根据其各自不同的特点有着不同的适用场景

  计数器的使用:假如我们现在需要一个用来计数的变量,那么我们就可以使用let来声明。

  var arr = []
  for(let i = 0; i < 10; i++) {
  arr[i] = () => {
  console.log(i)
  } // 利用计数进行操作
  }
  arr[7]() // 7


  for(var i = 0; i < 10; i++) {
  arr[i] = () => {
  console.log(i)
  } // 利用计数进行操作
  }
  arr[7]() // 10

  上述可以看到var和let的输出结果,也就知道这两个适用场景是不同的,两者之间差距也就显现出来。

  for循环中的父子关系:for循环中有两个作用域,即父作用域与子作用域,设置循环变量的部分为父作用域,循环体内部为子作用域

  for(let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i)
  }
  // abc
  // abc
  // abc

  上面的例子循环打出了三个abc就说明了两个i的作用域不同,如果不在循环体内声明的话将会打印出0,1,2

  块级作用域

  ES6新增了块级作用域,此前ES5只有全局作用域函数作用域

  全局作用域:window对象的所有属性都具有全局作用域,可以在程序的任意位置访问,拥有全局作用域的变量。

  函数作用域:也可以叫做局部作用域,意思就是每一个函数中都有一个函数作用域或者嵌套更多的函数作用域,在函数作用域中定义的变量只能在该函数作用域内部使用。

  概念

  块级作用域的出现其实是由新增声明let产生的

  let n = 5
  function fn() {
  if(true) {
  let n = 10
  }
  console.log(n)
  }
  fn() // 5

  上面的例子诠释了块级作用域的作用,即外层代码块不受内层代码块的影响,我们在if函数体内声明的n只有在if函数体内可以访问,而fn中访问n不受if内层的声明影响。

  存在意义

  var tmp = new Date();
  function fn() {
  console.log(tmp);
  if(false) {
  var tmp = 'hello world'
  }
  }
  fn()

  如上,存在函数作用域全局作用域,正常情况下fn()函数体内if函数体外是使用外层即var tmp = new Date();但是由于变量提升现象的存在即if函数体内的var tmp = 'hello world'发生了变量提升,即fn()函数体内的编译形式如下,所以输出结果为undefined。

  function fn() {
  var tmp
  console.log(tmp);
  tmp = 'hello world'
  }

  而块级作用域正是解决了这个问题

 

 let n = 5
  function fn() {
  if(true) {
  let n = 10
  }
  console.log(n)
  }
  fn() // 5

  除此之外还可以防止局部作用域变量的泄露到全局当中

  let arr = [1,2,3]
  for(var i = 0; i < arr.length; i++) {
  console.log(arr[i])
  }
  {
  console.log(i) // 3
  }

  上述中其实让变量泄露,也就是i变量被泄露到了整个全局中,但使用i is not defined,就可以说明变量未被泄露到全局中。

 

 let arr = [1,2,3]
  for(let i = 0; i < arr.length; i++) {
  console.log(arr[i])
  }
  console.log(i) // i is not defined

  const命令

  基本使用

  const声明的变量无法被再次赋值改变,且声明的时候必须赋值

  const name = '猪痞恶霸'
  name = 'fzf404' // Assignment to constant variable.


  const name // Missing initializer in const declaration
  name = '猪痞恶霸'

  const与let的特性很像,比如只在其声明的块级作用域内有效,存在暂时性死区

  不可被const的情况

  javascript中有两种数据类型即:简单数据类型复杂数据类型

  简单数据类型:数值,字符串,布尔值

  复杂数据类型:数组,对象

  我们看到两种数据类型的访问方式不同,简单数据类型的值直接保存变量所指向的内存地址,这样在直接访问值而复杂数据类型的访问是通过变量指向的内存地址,内存地址保存的是另一个指针(引用)

  现在我们说说const声明,由它所指向变量的那个内存地址不能改动,因此const声明的复杂数据类型,就不会让现数组的元素和对象的属性可以发生改变

  const person = {}
  person.name = "猪痞恶霸"
  console.log(person.name) // 猪痞恶霸

  请大家关注后续更多精彩内容。


文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/127971.html

相关文章

  • ES6核心特性

    摘要:报错不报此外还有个好处就是简化回调函数正常函数写法箭头函数写法改变指向长期以来,语言的对象一直是一个令人头痛的问题,在对象方法中使用,必须非常小心。 前言 ES6 虽提供了许多新特性,但我们实际工作中用到频率较高并不多,根据二八法则,我们应该用百分之八十的精力和时间,好好专研这百分之二十核心特性,将会收到事半功倍的奇效!写文章不容易,请大家多多支持与关注!本文首发地址GitHub博客(...

    loostudy 评论0 收藏0
  • ES6核心特性

    摘要:报错不报此外还有个好处就是简化回调函数正常函数写法箭头函数写法改变指向长期以来,语言的对象一直是一个令人头痛的问题,在对象方法中使用,必须非常小心。 前言 ES6 虽提供了许多新特性,但我们实际工作中用到频率较高并不多,根据二八法则,我们应该用百分之八十的精力和时间,好好专研这百分之二十核心特性,将会收到事半功倍的奇效!写文章不容易,请大家多多支持与关注!本文首发地址GitHub博客(...

    _DangJin 评论0 收藏0
  • ES6新特性总结 一

    摘要:一旦声明,常量的值不能被改变。顶层对象的属性顶层对象,浏览器中指的是对象,在中指的是对象。中新增了两个命令和,命令用于暴露出模块对外的接口,而则用于输入某一模块。 1.声明变量的关键字:const 和 let JavaScript ES6中引入了另外两个声明变量的关键字:const和let。在ES6中,我们将很少能看到var了。 const关键字 const声明一个只读的常量。一旦声明...

    MarvinZhang 评论0 收藏0
  • 如何设置node全局脚本

    摘要:全局脚本设置的本质思路其实原理很简单将的全局命令搜索路径,加上脚本所在文件夹的路径。权限设置了以后,脚本的图标将变成下面这个样子。重启或新建终端,执行脚本。 前语 随着node的流行,JS已经可以解决大部分问题。这对前端工程师十分友好。相信很多同学在开发业务之余,都会写一些小脚本代替手工完成繁琐,重复的工作,从而提高工作效率。但部分同学开发的脚本,仅局限于脚本所在路径,通过node x...

    cgspine 评论0 收藏0
  • 深入理解Node.js 进程线程(8000长文彻底搞懂)

    摘要:在单核系统之上我们采用单进程单线程的模式来开发。由进程来管理所有的子进程,主进程不负责具体的任务处理,主要工作是负责调度和管理。模块与模块总结无论是模块还是模块,为了解决实例单线程运行,无法利用多核的问题而出现的。 前言 进程与线程是一个程序员的必知概念,面试经常被问及,但是一些文章内容只是讲讲理论知识,可能一些小伙伴并没有真的理解,在实际开发中应用也比较少。本篇文章除了介绍概念,通过...

    Harpsichord1207 评论0 收藏0

发表评论

0条评论

3403771864

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<