上面可以看见,在函数中var声明的变量在函数外面是访问不到的,而在块中通过var声明的变量在块外面是能访问的,这就是说var是函数作用域,只有函数能约束他的作用范围,而代码块是做不到约束var定义变量的范围的。所以下面两个段代码效果是一样的
var j = 0;
console.log(j) // j = 0
console.log(j) // j = 0
// 根据变量提升原则可以改为下面的式子
var j;
j = 0;
console.log(j) // j = 0;
console.log(j) // j = 0;
let声明的变量和var声明的变量就作用域问题就是,let声明的变量是块级作用域;
块级作用域:
// 和var声明变量的例子比较
let i = 0;
console.log(i) // i = 0;
console.
声明变量的关键字var , let ,const。var是函数作用域,let,const是块级作用域。这里就来谈谈关于函数作用域和块级作用域,通过一个for循环的例子来解答两个作用域的差别,以及如何通过var声明来模拟let的特性。
window.onload = function () {
for (
var
i = 0; i < 5; i++) {
setTimeout(() => { console.log(i) }, 200)
for (
let
k = 0; k < 5; k++) {
setTimeout(() => { console.log(k
for (
var
i = 0; i < 3; i++) {
setTimeout(function() { // 同步注册回调
函数
到 异步的 宏任务队列。
console.log(i); // 执行此代码时,同步代码for
循环
已经执行完成
}, 0);
在使用
var
的时候,最常见的问题就是对迭代变量的奇特声明和修改:
之所以会这样,是因为在退出
循环
时,迭代变量保存的是导致
循环
退出的值:5。在之后执行超时
逻辑时,所有的 i 都是同一个变量,因而输出的都是同一个最终值。
而在使用
let
声明迭代变量时,
JavaScript
引擎在后台会为每个迭代
循环
声明一个新的迭代变量。
每个 setTimeout 引用的都是不同的变量实例,所以 console.log 输出的是我们期望的值,也就是循
环执行过程
中
每个迭代变量的值。
这种每次迭代声明一个独立变量实例的
在理解
var
、
let
、const三者在声明变量的区别时,遇到了一道十分有意思的题:<body>
<ul>
<li>第一个li</li>
<li>第二个li</li>
<li>第三个li</li>
<li>第四个li</li>
for
循环
体内的计数器 i ,如果使用
let
声明,在
循环
体外使用计数器 i,会报错。如果使用
var
声明,在
循环
体外使用计数器 i,不会报错。这是因为
let
声明的变量仅在其所在的
块级
作用域
内有效。
var
声明的变量 i,在全局范围内都有效,所以全局只有一个变量 i。每一次
循环
,变量 i 的值都会发生改变,而
循环
内
函数
内部的
中
的 i 指向全局的 i。也就是说,所有
函数
内部的 i 指向的都是同一个 i,导致运行时输出的是最后一轮的 i 值。如果使用
let
,声明的变量仅在
块级
作用域
内有效,当前的 i
初学
JavaScript
时,都会听前辈建议不要用
var
声明变量,
es6
以后要用
let
,道理是啥也没当回事,直到for
循环
时候才发现
循环
条件for(
var
i=0;i<arr.length;i++)
中
的i是一个i,这就导致做点击事件的时候,无论谁点击,结果i都是退出
循环
后最终的i固定不变。其实这个问题在C#
中
压根不是问题........最后查了下,再加上技术群大佬们的指点,终于理解了原因。接下来就举例子给大家详细说明下。
开门见山,先说核心结论。若不理解请继续往后读,相信读完全文再回头看你一定会深有体
来源:exploringjs.com/
es6
/ch_
var
i…
ES6
提供了两种声明变量的新方法:
let
和 const ,它们主要取代 ES5 声明变量的方式:
var
。
9.1.1
let
let
与
var
类似,但它声明的变量是具有
块级
作用域
的(block-scoped),它只存在于当前块
中
。
var
是
函数
作用域
(function-scoped)。
在下面的代码
中
,您可以看到 l...