Javascript中的var、let、const

ECMAScript变量是松散类型的,变量可以用于保存任何类型的数据,每个变量不过是一个用于保存任意值的命名占位符。有3个关键字可以声明变量,var、let和const。其中let和const是ES6新增关键字。

var关键字

1、var声明作用域

使用var定义的变量会成为包含它的函数的局部变量

function test() {
  var name = 'Mike'
  console.log(name) // 'Mike'
}
console.log(name) // ReferenceError: name is not defined
2、var声明提升

使用var时,下面的代码不会报错,因为用var声明的变量会自动提升到函数作用域顶部:

function test() {
  console.log(name)
  var name = 'Mike'
}
test() // undefined

之所以不会报错是因为ECMAScript运行时把它看成等价于如下的代码:

function test() {
  var name
  console.log(name)
  name = 'Mike'
}
test() // undefined

可以多次使用var声明同一个变量

var age = 10
var age = 20
var age = 30
console.log(age) // 30

let关键字

let和var最明显的区别是:let声明的范围是块作用域,var声明的范围是函数作用域

if (true) {
  var name = 'Mike'
  console.log(name) // Mike
}
console.log(name) // Mike

if (true){
  let name = 'Mike'
  console.log(name) // Mike
}
console.log(name) // ReferenceError: name is not defined

let不允许同一个块作用域中出现冗余声明,会报错:

let age = 10
let age = 20
console.log(age) // SyntaxError: Identifier 'age' has already been declared

对声明冗余报错不会因混用let和var而受影响

var name
let name
console.log(name) // Identifier 'name' has already been declared

let name
var name
console.log(name) // Identifier 'name' has already been declared
暂时性死区

let和var的另一个重要区别是let声明的变量不会在作用域中被提升

console.log(name)
let name = 'Mike' // ReferenceError: Cannot access 'name' before initialization

在解析代码时,js引擎会注意到后面的let关键字,也会给变量分配空间,但在此之前不能用任何方式来引用未声明的变量。在let声明之前的执行瞬间被称为 “暂时性死区”

for循环中的let声明

for循环中使用var定义的迭代变量会渗透到循环体外部

for(var i = 0; i < 5; i++){}
console.log(i) // 5

改成let声明后这种情况就消失了

for(let i = 0; i < 5; i++){}
console.log(i) // ReferenceError: i is not defined

使用var时最常见的问题是对迭代变量的奇特声明和修改

for(var i = 0; i < 5; i++){
  setTimeout(() => {
    console.log(i)
  }, 0)
} // 5,5,5,5,5

输出的值并不是0, 1, 2, 3, 4,因为在退出循环时迭代变量保存的是导致退出循环的值5。之后执行超时逻辑时,所有的i都是同一个变量。而let声明迭代变量时js引擎会为每个迭代循环声明一个新的迭代变量。每个setTimeout引用的都是不同的变量。

for(let i = 0; i < 5; i++){
  setTimeout(() => {
    console.log(i)
  }, 0)
} // 0, 1, 2, 3, 4

const关键字

const和let基本相同,唯一一个重要的区别是它声明变量时必须同时初始化,且不能修改

const name = 'Mike'
name = 'Lily' // TypeError: Assignment to constant variable.

// 不允许重复声明
const name = 'Mike'
const name = 'Lily' // SyntaxError: Identifier 'name' has already been declared

// const声明的作用域也是块
if (true) {
  const name = 'Mike'
  console.log(name)
}
console.log(name) // ReferenceError: name is not defined

const声明到应用到顶级原语或者对象。也就是说赋值为对象的const变量不能再被重新赋值为其他引用值,但对象的键不受限制

const obj1 = {}
obj1 = {} // TypeError: Assignment to constant variable.

const obj2 = {}
obj2.name = 'Mike'
console.log(obj2) // { name: 'Mike' }

如果想让整个对象不能修改,可以使用Object.freeze()。即使改变对象属性不会报错,但是会失败。

const obj2 = Object.freeze({})
obj2.name = 'Mike'
console.log(obj2) // {}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值