详解js中let与var声明变量的区别
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 明确规定,如果区块中存在let
和const
命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用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 匿名函数(anonymous function)与闭包(closure)
JavaScript 匿名函数(anonymous function)与闭包(closure) ,学习js的朋友可以参考下。2011-10-10JavaScript 双向链表操作实例分析【创建、增加、查找、删除等】
这篇文章主要介绍了JavaScript 双向链表操作,结合实例形式分析了JavaScript双向链表的创建、增加、查找、删除等相关操作技巧,需要的朋友可以参考下2020-04-04
最新评论