详解js中let与var声明变量的区别


Posted in Javascript onApril 05, 2020

ES6 新增了let命令,用来声明局部变量,所声明的变量,只在let命令所在的代码块内有效,而且有暂时性死区的约束。

1.ES6可以用let定义块级作用域变量

代码如下:

function f1(){
  {
   var a = 10;
   let b = 20;
  }
  console.log(a); // 10
  console.log(b); // Uncaught ReferenceError: b is not defined
 }
 f1();

说明:在ES6之前只有全局作用域和函数作用域,在ES6中新增了块级作用域,用{}花括号表示。var 声明的变量a在花括号外面仍然是会起作用的,但是let声明的变量b只有在花括号里面才会起作用的,在块级作用域内。

2.let配合for循环的独特应用

代码如下:

function f2(){
  var i = 5;
  for(var i=0;i<=10;i++){

  }
  console.log(i); // 11

  var j = 5;
  for(let j=0;j<=10;j++){

  }
  console.log(j); // 5

 }
 f2();

说明:let非常适合用于for循环内部的块级作用域,在for循环当中,每一次的执行都是一个全新的独立的块级作用域。使用let声明的变量在for循环当中不会受到循环体外面的影响,不会受到变量污染,不会发生改变。对于var声明的变量i会受到for循环的影响,受到变量污染,而let声明的变量j不会受到for循环的影响。

3.let没有变量提升与暂时性死区

代码如下:

function f3(){

  // 变量提升
  function f31(){
   console.log(a); // undefined
   var a = 10;

   console.log(b); // Uncaught ReferenceError: b is not defined
   let b = 10;
  }
  f31();

说明:在ES6中,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。暂时性死区(TDZ):在代码块内,使用let命令声明变量之前,该变量都是不可用的。在f31函数中,用var声明的变量a发生了变量提升,打印出的值为undefined 未定义,而用let声明的变量b报错Uncaught ReferenceError,不会发生变量提升。在f32函数中,用使用let命令声明的变量a之前,都属于变量a的暂时性死区,形成封闭作用域,该变量都是不可用的,会报错,Uncaught ReferenceError: a is not defined。在let声明变量后,它是一个未定义的变量。当再给变量a进行赋值操作以后,它的值可以正常打印出来。

4.let变量不能重复声明

代码如下:

function f4(){
  let a = 10;
  let a = 20;
  console.log(a); // Uncaught SyntaxError: Identifier 'a' has already been declared

  let b = 10;
  var b = 20;
  console.log(b); // Uncaught SyntaxError: Identifier 'b' has already been declared

 }
 f4();

说明:let不允许在相同作用域内,重复声明同一个变量,否则报错。在函数f4中,无论是用两个let声明同一个变量a,还是一个let声明变量b和一个var声明变量b,都是会报错的,Uncaught SyntaxError: Identifier ‘a' has already been declared 和 Uncaught SyntaxError: Identifier ‘b' has already been declared , 所以不能够重复声明同一个变量。

JS中的let和var的区别补充

最近很多前端的朋友去面试被问到let和var的区别,其实阮一峰老师的ES6中已经很详细介绍了let的用法和var的区别。我简单总结一下,以便各位以后面试中使用。

ES6 新增了let命令,用来声明局部变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效,而且有暂时性死区的约束。

先看个var的常见变量提升的面试题目:

//题目1:
var a = 99;      // 全局变量a
f();          // f是函数,虽然定义在调用的后面,但是函数声明会提升到作用域的顶部。 
console.log(a);    // a=>99, 此时是全局变量的a
function f() {
 console.log(a);   // 当前的a变量是下面变量a声明提升后,默认值undefined
 var a = 10;
 console.log(a);   // a => 10
}

// 输出结果:
undefined
10
99

如果以上题目有理解困难的童鞋,请系统的看一下老马的免费JS高级视频教程。

ES6可以用let定义块级作用域变量

在ES6之前,我们都是用var来声明变量,而且JS只有函数作用域和全局作用域,没有块级作用域,所以{}限定不了var声明变量的访问范围。

例如:

{ 
 var i = 9;
} 
console.log(i); // 9

ES6新增的let,可以声明块级作用域的变量。

{ 
 let i = 9;   // i变量只在 花括号内有效!!!
} 
console.log(i); // Uncaught ReferenceError: i is not defined

let 配合for循环的独特应用

let非常适合用于 for循环内部的块级作用域。JS中的for循环体比较特殊,每次执行都是一个全新的独立的块作用域,用let声明的变量传入到 for循环体的作用域后,不会发生改变,不受外界的影响。看一个常见的面试题目:

for (var i = 0; i <10; i++) { 
 setTimeout(function() { // 同步注册回调函数到 异步的 宏任务队列。
  console.log(i);    // 执行此代码时,同步代码for循环已经执行完成
 }, 0);
}
// 输出结果
10  共10个
// 这里面的知识点: JS的事件循环机制,setTimeout的机制等

如果把 var改成 let声明:

// i虽然在全局作用域声明,但是在for循环体局部作用域中使用的时候,变量会被固定,不受外界干扰。
for (let i = 0; i < 10; i++) { 
 setTimeout(function() {
  console.log(i);  // i 是循环体内局部作用域,不受外界影响。
 }, 0);
}
// 输出结果:
0 1 2 3 4 5 6 7 8 9

let没有变量提升与暂时性死区

用let声明的变量,不存在变量提升。而且要求必须 等let声明语句执行完之后,变量才能使用,不然会报Uncaught ReferenceError错误。
例如:

console.log(aicoder);  // 错误:Uncaught ReferenceError ...
let aicoder = 'aicoder.com';
// 这里就可以安全使用aicoder

ES6 明确规定,如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。

let变量不能重复声明

let不允许在相同作用域内,重复声明同一个变量。否则报错:Uncaught SyntaxError: Identifier 'XXX' has already been declared

例如:

let a = 0;
let a = 'sss';
// Uncaught SyntaxError: Identifier 'a' has already been declared

总结

ES6的let让js真正拥有了块级作用域,也是向这更安全更规范的路走,虽然加了很多约束,但是都是为了让我们更安全的使用和写代码。

以上所述是小编给大家介绍的let与var声明变量区别详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
JavaScript下申明对象的几种方法小结
Oct 02 Javascript
DOM节点深度克隆函数cloneNode()用法实例
Jan 12 Javascript
jQuery实现菜单感应鼠标滑动动画效果的方法
Feb 28 Javascript
jquery 插件实现多行文本框[textarea]自动高度
Mar 04 Javascript
jQuery Mobile开发中日期插件Mobiscroll使用说明
Mar 02 Javascript
JS ES6中setTimeout函数的执行上下文示例
Apr 27 Javascript
jQuery+Ajax请求本地数据加载商品列表页并跳转详情页的实现方法
Jul 12 jQuery
vue 计时器组件的实现代码
Sep 14 Javascript
微信小程序支付之c#后台实现方法
Oct 19 Javascript
玩转Koa之核心原理分析
Dec 29 Javascript
JavaScript解析及序列化JSON的方法实例分析
Jan 04 Javascript
JS常用正则表达式超全集(密码强度校验,金额校验,IE版本,IPv4,IPv6校验)
Feb 03 Javascript
webpack中如何加载静态文件的方法步骤
May 18 #Javascript
微信小程序实现录音时的麦克风动画效果实例
May 18 #Javascript
vue+egg+jwt实现登录验证的示例代码
May 18 #Javascript
egg.js的基本使用和调用数据库的方法示例
May 18 #Javascript
inquirer.js一个用户与命令行交互的工具详解
May 18 #Javascript
webpack 代码分离优化快速指北
May 18 #Javascript
如何实现小程序tab栏下划线动画效果
May 18 #Javascript
You might like
风味层面去分析咖啡油脂
2021/03/03 咖啡文化
PHP 木马攻击防御技巧
2009/06/13 PHP
PHP下对数组进行排序的函数
2010/08/08 PHP
探讨fckeditor在Php中的配置详解
2013/06/08 PHP
如何解决PHP无法实现多线程的问题
2015/09/25 PHP
PHP实现按之字形顺序打印二叉树的方法
2018/01/16 PHP
lnmp安装多版本PHP共存的方法详解
2018/08/02 PHP
【消息提示组件】,兼容IE6/7&amp;&amp;FF2
2007/09/04 Javascript
JS在IE和FF下attachEvent,addEventListener学习笔记
2009/11/26 Javascript
JSON为什么那样红为什么要用json(另有洞天)
2012/12/26 Javascript
兼容最新firefox、chrome和IE的javascript图片预览实现代码
2014/08/08 Javascript
检测一个函数是否是JavaScript原生函数的小技巧
2015/03/13 Javascript
javascript中对变量类型的判断方法
2015/08/09 Javascript
详解javascript函数的参数
2015/11/10 Javascript
微信小程序 用户数据解密详细介绍
2017/01/09 Javascript
使用jQuery实现简单的tab框实例
2017/08/22 jQuery
webpack3之loader全解析
2017/10/26 Javascript
vue 表单输入格式化中文输入法异常问题
2018/05/30 Javascript
[01:15:44]首部DOTA2纪录片今日23时全网上映
2014/03/19 DOTA
python实现在pickling的时候压缩的方法
2014/09/25 Python
浅析Python中yield关键词的作用与用法
2016/11/29 Python
Python3+django2.0+apache2+ubuntu14部署网站上线的方法
2018/07/07 Python
Python wxPython库消息对话框MessageDialog用法示例
2018/09/03 Python
python运行时强制刷新缓冲区的方法
2019/01/14 Python
python实现对服务器脚本敏感信息的加密解密功能
2019/08/13 Python
python定时任务 sched模块用法实例
2019/11/04 Python
Python语法之精妙的十个知识点(装B语法)
2020/01/18 Python
澳大利亚波希米亚风时尚品牌:Tree of Life
2019/09/15 全球购物
汽车销售求职自荐信
2013/10/01 职场文书
诚信考试倡议书
2014/04/15 职场文书
医院营销工作计划
2015/01/16 职场文书
培根随笔读书笔记
2015/07/01 职场文书
创业者如何撰写出一份打动投资人的商业计划书?
2019/07/02 职场文书
Python基础之进程详解
2021/05/21 Python
SpringBoot实现quartz定时任务可视化管理功能
2021/08/30 Java/Android
Java 通过手写分布式雪花SnowFlake生成ID方法详解
2022/04/07 Java/Android