《JavaScript高级程序设计》学习笔记(一)- var、let 和 const

变量声明

ECMAScript 变量是松散类型的,变量可以用于保存任何类型的数据,每个变量只不过是一个用于保存任意值的命名占位符。有三个关键字可以声明变量:varletconst。其中var在所有版本中都可以使用,而letconst只能在 ECMAScript6 及之后版本中使用。

1. var关键字

var message

定义一个名为message的变量,可以用于保存任何类型的值。在不初始化的情况下,变量会保存一个特殊值undefined

var message = 'hi'
message = 100 // 合法,但不推荐

在声明的同时可以进行初始化。变量的初始化只是简单的赋值,并不标识变量类型,之后不仅可以改变变量保存的值,还可以改变值的类型。

1.1 var声明作用域

使用var操作符在全局作用域中声明的变量将成为window对象的属性。

var name = 'Stan'
console.log(window.name) // Stan

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

function test() {
  var message = 'h1' // 局部变量
}
test() // 函数调用之后其中的局部变量即被销毁
console.log(message) // error

在函数内定义变量时省略var操作符,将创建一个全局变量。(在严格模式下将抛出ReferenceError

function test() {
  message = 'hi' // 全局变量
}
test()
console.log(message) // hi

可以在一条语句中定义多个变量,并进行初始化(可选的)。

var message = 'hi',
  age = 20,
  found = false

1.2 var声明提升

使用var操作符声明的变量会自动提升到函数作用域的顶部。变量提升(hoist)指的是将变量声明提升到函数作用域的顶部。

function foo() {
  console.log(age)
  var age = 20
}
foo() // undefined

/* 等价于 */
function foo() {
  var age
  console.log(age)
  age = 20
}

此外,可以多次使用var声明同一个变量,而letconst均不允许在作用域内出现冗余声明。混用三个操作符也要遵从操作符的规则。

var age = 20
var age = 21
var age = 22
console.log(age) // 22

let name
let name // SyntaxError

var name = 'xiaoming'
var name = 'xiaohong' // OK
let name // SyntaxError

let age
var age // SyntaxError

2. let关键字

letvar的作用类似,主要区别在于,let声明的范围是块作用域,而var声明的范围是函数作用域。

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

if (true) {
  let age = 20 // 作用域仅限于当前块
  console.log(age) // 20
}
console.log(age) // ReferenceError

JavaScript 引擎会记录用于变量声明的标识符及其所在的块作用域,因此嵌套使用相同标识符不会报错,因为同一个块中没有重复声明。

var name = 'xiaoming'
let age = 20
console.log(name) // xiaoming
console.log(age) // 20
if (true) {
  var name = 'xiaohong'
  let age = 19
  console.log(name) // xiaohong
  console.log(age) // 19
}

2.1 暂时性死区

letvar的另一个重要区别在于,let声明的变量不会在作用域内被提升。

console.log(name) // undefined
console.log(age) // ReferenceError
var name = 'xiaoming'
let age = 20

在解析代码时,JavaScript 引擎也会注意到出现在块后部的let声明,但在此之前不能以任何方式来引用未声明的变量,否则将抛出ReferenceError。在let声明前的执行瞬间称为暂时性死区(temporal dead zone)。

2.2 全局声明

var关键字不同,使用let在全局作用域中声明的变量不会成为window对象的属性。

let age = 10
console.log(window.age) // undefined

2.3 条件声明

JavaScript 不支持条件声明。


使用try/catch语句或typeof操作符也无法解决,因为条件块中let声明的作用域仅限于该块。

if (typeof name === 'undefined') {
  let name // name的作用域仅限于此块作用域
}
name = 'Stan' // 无法达到目的,形同全局赋值
try {
  console.log(age) // 若未声明age,则会报错
} catch (error) {
  let age // age的作用域仅限于此块作用域
}
age = 20 // 无法达到目的,形同全局赋值

2.4 for循环中的let声明(包括for-infor-of循环)

for (var i = 0; i < 5; i++) {}
console.log(i) // 5
for (var j = 0; j < 5; j++) {
  setTimeout(() => console.log(j))
}
// 5 5 5 5 5
for (let m = 0; m < 5; m++) {}
console.log(m) // ReferenceError
for (let n = 0; n < 5; n++) {
  setTimeout(() => console.log(n))
}
// 1 2 3 4 5

3. const关键字

const关键字与let基本相同,唯一重要的区别在于使用const关键字声明时必须同时初始化变量,且不能修改该变量的值,否则将抛出SyntaxError

const声明的变量只适用于它指向的变量的引用,即若const变量引用一个对象,修改该对象内部的属性并不违反const的限制。

4. 声明风格及最佳实践

const优先,let次之,不使用var

你可能感兴趣的:(javascript前端es6)