这样理解Javascript中let/var区别

原创 2021-07-18 本文共3350个字,预计耗時9分钟 772次阅读
文章摘要:自从ES6引入了变量定义的新关键词const和let后,不少人都会关系到底跟之前的var关键词有何区别,在今后的js开发中怎么使用;在写这篇文章之前也是看了不少教程,讲解的都是差不多的意思,但是还是很难理解,在写下这篇文章前通了,所以记录下...

这样理解Javascript中let/var区别

自从ES6引入了变量定义的新关键词const和let后,不少人都会关系到底跟之前的var关键词有何区别,在今后的js开发中怎么使用;在写这篇文章之前也是看了不少教程,讲解的都是差不多的意思,但是还是很难理解,在写下这篇文章前通了,所以记录下来。

var,let和const异同

首先const比较容易区别开来,一句话,const就是定义不变的值,一些常量等不需要改变的值;比较难以理解主要集中在let和var的区别,当你发现有了let这个新关键词定义变量的时候,去百度相关教程,几乎所有的教程文字视频都在告诉你let有块级作用域,而var没有。是不是一脸懵逼,什么块级作用域,区别体现在哪里?

那到底什么块级作用域,怎么才能比较好理解这二者的区别,怎样才能通俗易懂的理解差别?

Javascript的块、块级作用域

JavaScript的块简单的来说就是用大括号”{}“,包裹起来的代码块,常见的if里的代码块,for里的代码块都是块。你也可以认为的将一段代码用大括号括起来就是一个块了。

知道了块,那么块级作用域自然好理解,就是在这个代码块里是个小天地,在这里面的定义的量怎么改变都不会影响到外面同名变量的值。

实例解释

还是没有理解吧,看一个在let出现前,一个比较难以理解的案例。当有多个按钮(如5个),对这些按钮都绑定点击事件,点击其中一个打印其索引值,我们会这么写:

HTML部分:

<button class="clicked">欠点</button>
<button class="clicked">欠点</button>
<button class="clicked">欠点</button>
<button class="clicked">欠点</button>
<button class="clicked">欠点</button>

js部分,获取按钮集合,依次绑定点击事件源码如下,当点击其中一个按钮 执行点击事件,会发现无论是哪个打印都是”5″

var clickedEl = document.getElementsByClassName('clicked');
for(var i= 0;i< clickedEl.length;i++){  
  console.log(i); // 0,1,2,3,4
  clickedEl[i].addEventListener('click',function(){
    console.log(i); // 打印了 5个 5
  })
}

代码详细以及执行结果截图如下面的:

代码执行截图

这里的问题相信很多初学JavaScript的童鞋们都会比较费解,不知道怎么去获取当前被点击的按钮的索引值,也会很费解为什么每个按钮点击的结果都是相同的。明明i从0到4都获取到了,最后却是打印5。这里就是因为var的申明的变量没有块级作用域的概念,造成了没有得到我们想要的结果。

处理方式

在let申明(ES6)出现之前的处理方式是将循环值“i”作为参数传入一个立即执行的匿名函数(闭包)来解决此问题:

var clickedEl = document.getElementsByClassName('clicked');
for(var i= 0;i< clickedEl.length;i++){  
  console.log(i); // 0,1,2,3,4
  (function(ii){   //闭包处理 立即执行匿名函数(function(){...})()
    clickedEl[ii].addEventListener('click',function(){
      console.log(i); //  当前点击的索引
    })
  })(i) //将i 作为参数传入匿名函数
}

而ES6到来之后,我们将for里的var变成let申明时,结果也是我们想要的:

var clickedEl = document.getElementsByClassName('clicked');
for(let i= 0;i< clickedEl.length;i++){   //let申明
  console.log(i); // 0,1,2,3,4
  clickedEl[i].addEventListener('click',function(){
    console.log(i); // 打印了 被点击的索引值
  })
}

let申明变量块级作用域

这个例子从足见let和var的区别之处,可能看了实例还是很难理解为什么一个块级作用域会影响这么大,可以这么理解,for循环是执行多次相同函数的过程,而每次执行都是一个块。

var/let申明for循环区别之处理解

当我们要一个函数执行多次的的时候我们会用到for循环,而var申明的情况如下:

for(var i= 0;i< 3;i++){
  console.log(i); // 0,1,2
  var clickedEl = document.getElementById('clicked');
  clickedEl.addEventListener('click',function(){
    console.log(i); 
  })
}

也就是里面的代码执行了三次,可以理解为下面的三个块:

// i = 0 一个块
{
  var i = 0;
  console.log(i); //0
  var clickedEl = document.getElementById('clicked');
  clickedEl.addEventListener('click',function(){
    console.log(i); //2
  })
}
// i = 1 一个块
{
  var i = 1;
  console.log(i); //1
  var clickedEl = document.getElementById('clicked');
  clickedEl.addEventListener('click',function(){
    console.log(i); //2
  })
}
// i = 2 一个块
{
  var i = 2;
  console.log(i); //2
  var clickedEl = document.getElementById('clicked');
  clickedEl.addEventListener('click',function(){
    console.log(i);  //2
  })
}

理解:因为var没有块级作用域概念 所以在一个新的块级里重新定义i时,改变的是全局的i值;clickedEl执行函数 click 时 i 已经最终的改变值(2)

let申明for里的变量时情况

for(let i= 0;i< 3;i++){
  console.log(i); // 0,1,2
  var clickedEl = document.getElementById('clicked');
  clickedEl.addEventListener('click',function(){
    console.log(i); 
  })
}

同样可以理解为三个块:

// i = 0 一个块
{
  let i = 0;
  console.log(i); //0
  var clickedEl = document.getElementById('clicked');
  clickedEl.addEventListener('click',function(){
    console.log(i); //0
  })
} // i = 1 一个块
{
  let i = 1;
  console.log(i); //1
  var clickedEl = document.getElementById('clicked');
  clickedEl.addEventListener('click',function(){
    console.log(i);//1
  })
}
// i = 2 一个块
{
  let i = 2;
  console.log(i); //2
  var clickedEl = document.getElementById('clicked');
  clickedEl.addEventListener('click',function(){
    console.log(i);//2
  })
}

理解:因为let有块级作用域 各个块里的i相互不影响,所以每个块里的i是独立的,打印的值就是块里的的值。

这样的理解是不是就比较好理解了,明明就是一个单词之差,结果却是天壤之别,将for的循环拆开为多个块就比较好理解了不是。另外在用闭包处理的时候,原理也是因为函数有作用域,将循环的i值作为函数参数传入匿名函数,达到不受全局变量的影响效果。

版权免责申明
① 本站源码模板等资源SVIP用户永久不限量免费下载
② 所有资源来源于网络收集,如有侵权,请联系站长进行删除处理。
③ 分享目的仅供大家学习和交流,请不要用于商业用途,否则后果自负。
④ 如果你有源码需要出售,可以联系管理详谈。
⑤ 本站提供的源码、模板、插件等等资源,都不包含技术服务请大家谅解。
⑥ 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需。
⑦ 在您的能力范围内,为了大环境的良性发展,请尽可能的选择正版资源。
⑧ 网站资源绝不做任何二次加密或添加后门(原版加密除外)
常见问题F&Q
需要积分的资源怎么下载?
您可以注册后签到等活跃动作获得积分,积分可下载,也可充值升级等级免费下载。
源码模板等文件安全吗?有没有后门病毒吗?
站内资源标有“已测试”标签的资源源码,表示已经在本地安装测试调试过才分享出来的,可以保证一定的安全;若不放心可以自行下载模板资源后使用D盾等查杀工具扫一遍确认安全。
本站网站模板等源码提供安装服务吗?
本站资源收集于网络并分享出来共同学习,不提供免费安装服务,模板源码安装等需要有一定熟悉度,小白用户可以下载资源后雇人安装调试。