详解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 相关文章推荐
jQuery 动画基础教程
Dec 25 Javascript
纯js实现div内图片自适应大小(已测试,兼容火狐)
Jun 16 Javascript
jQuery实现contains方法不区分大小写的方法
Feb 13 Javascript
jQuery+json实现动态创建复杂表格table的方法
Oct 25 Javascript
Jquery EasyUI $.Parser
Jun 02 jQuery
解析Json字符串的三种方法日常常用
May 02 Javascript
使用vue-router为每个路由配置各自的title
Jul 30 Javascript
在AngularJs中设置请求头信息(headers)的方法及不同方法的比较
Sep 04 Javascript
JavaScript数据结构与算法之二叉树遍历算法详解【先序、中序、后序】
Feb 21 Javascript
vue 项目打包时样式及背景图片路径找不到的解决方式
Nov 12 Javascript
uni-app如何页面传参数的几种方法总结
Apr 28 Javascript
基于postman获取动态数据过程详解
Sep 08 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
ftp类(example.php)
2006/10/09 PHP
PHP 验证码不显示只有一个小红叉的解决方法
2013/09/30 PHP
PHP命名空间(namespace)的动态访问及使用技巧
2014/08/18 PHP
基于jQueryUI和Corethink实现百度的搜索提示功能
2016/11/09 PHP
JavaScript基础教程之alert弹出提示框实例
2014/10/16 Javascript
jQuery简单实现QQ空间点赞已经取消点赞
2015/04/02 Javascript
超实用的JavaScript代码段 附使用方法
2016/05/22 Javascript
Jquery通过ajax请求NodeJS返回json数据实例
2016/11/08 NodeJs
解决Vue 浏览器后退无法触发beforeRouteLeave的问题
2017/12/24 Javascript
js获取form表单中name属性的值
2019/02/27 Javascript
搭建Vue从Vue-cli到router路由护卫的实现
2019/11/14 Javascript
vue组件内部引入外部js文件的方法
2020/01/18 Javascript
python中requests模块的使用方法
2015/04/08 Python
Python简单格式化时间的方法【strftime函数】
2016/09/18 Python
使用python遍历指定城市的一周气温
2017/03/31 Python
解决Python 中英文混输格式对齐的问题
2018/07/16 Python
pytorch中tensor的合并与截取方法
2018/07/26 Python
CentOS7安装Python3的教程详解
2019/04/10 Python
Django中密码的加密、验密、解密操作
2019/12/19 Python
css3 clip实现圆环进度条的示例代码
2018/02/07 HTML / CSS
工作失误检讨书范文大全
2014/01/13 职场文书
初中体育教学反思
2014/01/14 职场文书
校园广播稿500字
2014/02/04 职场文书
顶碗少年教学反思
2014/02/21 职场文书
项目经理聘任书
2014/03/29 职场文书
优秀电子工程系毕业生求职信
2014/05/24 职场文书
服务宗旨标语
2014/07/01 职场文书
电子工程求职信
2014/07/17 职场文书
党支部班子“四风”问题自我剖析材料
2014/09/28 职场文书
九九重阳节标语
2014/10/07 职场文书
实习计划书范文
2015/01/16 职场文书
Python使用sql语句对mysql数据库多条件模糊查询的思路详解
2021/04/12 Python
Matplotlib绘制混淆矩阵的实现
2021/05/27 Python
Java多条件判断场景中规则执行器的设计
2021/06/26 Java/Android
Python torch.flatten()函数案例详解
2021/08/30 Python
Nginx安装配置详解
2022/06/25 Servers