JS中var、let、const的区别

var关键字:

  • var声明的范围是函数作用域;即:var在函数内部声明一个变量,那么这个变量是该函数的局部变量,只有在函数内部才能访问,函数外部无法访问(当然如果用闭包可以实现从外部访问,关于闭包:JS中的闭包
  • var 关键字在全局全局作用域中声明的变量会成为window对象的属性
  • 如果在非严格模式下的函数中,未用var声明就给一个变量赋值,那么该变量会变成全局变量,即在函数外部也可访问;而在严格模式下这样给未声明的变量赋值会报错ReferenceError(未定义/引用错误)
function test(){
  num = 100;    // 全局变量
}
test();
  • 用var声明的变量会自动提升到函数作用域的顶部,需要注意的是,声明提升只是提升变量声明,并不会提升变量赋值,所以下边的代码输出是undefined,而不是2020:
function test(){
  console.log(year);    // 不会报错,控制台输出:undefined
  var year = 2020;
}
test();
//  var声明提升后,上面的代码等价于下面:
function test(){
   var year;     // 声明提升不会提升变量赋值
   console.log(year);
   year = 2020;
}

let关键字:

  • let关键字的作用范围是块级作用域;块简单的理解就是用{ }包起来的一个范围,所以块级作用域是函数作用域的子集;在下边的代码中,num的块级作用域是if{ },所以在if{ }外部打印这个变量会报错
function test(){
  if(true){
     let num = 100;
     console.log(num);    // 输出:100
  }
  console.log(num);    // 报错ReferenceError: num 没有定义
} 
test();
  • let 不允许冗余声明,而var可以;
var num = 10;
var num = 100;
console.log(num);    // 输出:100

let year = 2018;
let year = 2020;
console.log(year);    // 报错SyntaxError:year已经声明过了
  • 对变量的冗余声明不会因为混用 let 和 var 而受影响,即如果分别用 let 和 var 对同一个变量进行声明,那么也是会报错;
let num = 100;
var num = 10;    // 报错SyntaxError:num已经声明过了

var year = 2018;
let year = 2020;    // 报错SyntaxError:year已经声明过了
  • let 关键字没有声明提升;在JS引擎解析代码时,会注意在块后边出现的 let 声明,但在此之前不能以任何方式来引用未声明的变量,否则会报错(ReferenceError)。在 let 声明之前执行的瞬间被称为“暂时性死区”。
console.log(num);    // ReferenceError:num 未定义
let num = 100;
  • let 关键字在全局作用域中声明的变量不会成为window对象的属性;但 let 声明依然是在全局作用域中发生的,相应变量会在页面生命周期内存续(因此要确保页面不会重复声明同一变量)

const关键字:

  • const声明变量时必须同时初始化变量,即给变量赋初值
  • 用const声明的变量是不能修改的,如果修改则会报错(TypeError)
const age = 18;
age = 20;    // 报错TypeError:给常量赋值
  • 但如果const指向的是一个对象,那么给这个对象里边的属性赋值是可以的
const per = {
    name: 'zhang',
    age: 18
}
per.age = 20;
console.log(per.age); // 输出:20
per.num = 100;
console.log(per.num); // 输出:100
  • const 其他行为和 let 基本相同:const 也不允许重复声明同一变量;作用域也是块级作用域

for 循环中的 var、let、const

for (var i = 0; i < 5; ++i) { 
 setTimeout(() => console.log(i), 0) 
}
// 输出5 5 5 5 5;而不是0 1 2 3 4;
/* 因为setTimeout会在for循环结束之后才会执行,
   而用var 声明的变量会渗透到循环的外部,在退出循环时,
   迭代变量 i 保存的是导致循环退出的值,即:i = 5;
   所以最后执行setTimeout()时也就输出:5 5 5 5 5
*/



for(let i = 0;i < 5;i++){
  setTimeout(() => console.log(i),0)
}
// 输出:0 1 2 3 4
/* 使用let 声明的迭代变量时,JS引擎会为每个迭代循环声明一个新的迭代变量
   所以最后执行setTimeout()时每次用的都是不同的变量,
   最后的输出结果也就是我们所期望的:0 1 2 3 4
   每次迭代声明一个独立变量实例的行为适用于所有风格的 for 循环,
   包括 for-in 和 for-of 循环
*/ 

 for (const i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(i);
    }, 0);
}
/**
 * 如果改成用const
 * 则会报错:TypeError: Assignment to constant variable(类型错误:给常变量赋值)
 * 然后打印一个0
 */


let i = 0; 
for (const j = 7; i < 5; ++i) { 
 console.log(j); 
} 
// 输出:7 7 7 7 7
// 每次迭代只是创建新的变量


for (const key in {a: 1, b: 2}) { 
 console.log(key); 
} 
// 输出:a b 
for (const value of [1,2,3,4,5]) { 
 console.log(value); 
} 
// 输出:1 2 3 4 5
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值