详解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 学习第七课 扩展jQuery的功能 插件开发
May 17 Javascript
IE与FireFox中的childNodes区别
Oct 20 Javascript
移动节点的jquery代码
Jan 13 Javascript
JS面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型模式)
Aug 16 Javascript
调试JavaScript中正则表达式中遇到的问题
Jan 27 Javascript
javascript中for/in循环及使用技巧
Sep 01 Javascript
jQuery实现下拉加载功能实例代码
Apr 01 Javascript
jQuery的图片轮播插件PgwSlideshow使用详解
Aug 11 Javascript
使用 Vue.js 仿百度搜索框的实例代码
May 09 Javascript
Javascript防止图片拉伸的自适应处理方法
Dec 26 Javascript
JavaScript类数组对象转换为数组对象的方法实例分析
Jul 24 Javascript
vscode 开发Vue项目的方法步骤
Nov 25 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
基于session_unset与session_destroy的区别详解
2013/06/03 PHP
php基于socket实现SMTP发送邮件的方法
2015/03/05 PHP
CodeIgniter开发实现支付宝接口调用的方法示例
2016/11/14 PHP
从阶乘函数对比Javascript和C#的异同
2012/05/31 Javascript
JS格式化数字金额用逗号隔开保留两位小数
2013/10/18 Javascript
jQuery实现统计复选框选中数量
2014/11/24 Javascript
JavaScript获取网页中第一个链接ID的方法
2015/04/03 Javascript
JS给Textarea文本框添加行号的方法
2015/08/20 Javascript
JS实现的N多简单无缝滚动代码(包含图文效果)
2015/11/06 Javascript
AngularJS模块学习之Anchor Scroll
2016/01/19 Javascript
JS 事件绑定、事件监听、事件委托详细介绍
2016/09/28 Javascript
用Vue.js实现监听属性的变化
2016/11/17 Javascript
js闭包用法实例详解
2016/12/13 Javascript
浅谈javascript中的 “ &amp;&amp; ” 和 “ || ”
2017/02/02 Javascript
JavaScript中清空数组的三种方式
2017/03/22 Javascript
微信小程序 WXML节点信息查询详解
2019/07/29 Javascript
浅谈laytpl 模板空值显示null的解决方法及简单的js表达式
2019/09/19 Javascript
Python Matplotlib库入门指南
2015/05/18 Python
Selenium定位元素操作示例
2018/08/10 Python
Python 运行 shell 获取输出结果的实例
2019/01/07 Python
python实现一行输入多个值和一行输出多个值的例子
2019/07/16 Python
python爬虫豆瓣网的模拟登录实现
2019/08/21 Python
python实现超市商品销售管理系统
2019/11/22 Python
如何基于Django实现上下文章跳转
2020/09/16 Python
Python requests HTTP验证登录实现流程
2020/11/05 Python
CSS3 transform的skew属性值图文详解
2014/07/21 HTML / CSS
AmazeUI图片轮播效果的示例代码
2020/08/20 HTML / CSS
老公给老婆的道歉信
2014/01/10 职场文书
教师节促销方案
2014/03/22 职场文书
个人事迹材料范文
2014/12/29 职场文书
2015年幼儿教育工作总结
2015/07/24 职场文书
自愿离婚协议书范本2016
2016/03/18 职场文书
《亲亲我的妈妈》观后感(3篇)
2019/09/26 职场文书
你知道哪几种MYSQL的连接查询
2021/06/03 MySQL
JavaScript的Set数据结构详解
2022/02/18 Javascript
Pandas-DataFrame知识点汇总
2022/03/16 Python