在 ES6 新增两种变数方法 let
、 const
,不过我们比较常把 const
叫做常数,主要是因为 var
的特性 容易触发 Bug , 这边与 var
的差异主要有:
在提及这些不同特性之前,先大致介绍一下这两个用法的差别。
let
能够重新赋值,但不能重复宣告
let String1 = 'test1'
String1 = 'test2'
let String1 = 'test3' // 重复宣告错误, Uncaught SyntaxError: Identifier 'String1' has already been declared
const
不能重新赋值,也不能重新宣告。
const String1 = 'test1'
const String1 = 'test2' // 重复宣告错误, Uncaught SyntaxError: Identifier 'String1' has already been declared
String1 = 'test3' // 赋值错误, Uncaught TypeError: invalid assignment to const 'String1'
要补充一点如果 const
的值是物件,对物件底下的属性赋值, const
则能接受这种操作继续使用。
const obj = {}
obj.name = 'Ryder'
console.log(obj) // { name: 'Ryder' }
const array = []
array.push(1)
console.log(array) // [1]
在过去 var
作用域是根据函式作用域,而 let
、 const
则是以 { ... }
Block 区块做为作用域,来看看以下范例:
var name1 = 'Ryder'
let name2 = 'Ryder'
function test(){
var name1 = 'Jack'
let name2 = 'Jack'
}
test()
console.log(name1, name2) // ?
结果是 Ryder, Ryder
,这范例很好理解,不论是 var
还是 let
, name = 'Jack'
的作用范围都只在 test()
这个函式中,console 的位置则是在全域,自然都会是 Ryder
,那麽再来看看这个范例:
var name1 = 'Ryder'
let name2 = 'Ryder'
{
var name1 = 'Jack'
}
{
let name2 = 'Jack'
}
console.log(name1 , name2) // ?
结果会是 Jack, Ryder
,这是因为上面提到的, let
是以 { ... }
区块做为作用域,因此 let name1 = 'Jack'
这个语法的有效范围只会存在於 { ... }
之中,而 var
则会被 { ... }
中的 var name1 = 'Jack'
,直接做替换,因此 name1
会是 'Jack'
。
这边要补充一下, 这边提到的 { ... }
并不是物件,而是一个作用域范围,主要是为了搭配 let
、 const
特性 ES6 才引入的,不过实做中通常不会刻意使用 { ... }
去区分作用域。
在提升章节我们有提到,JavaScript 在编译程序码时,会分为两个阶段:
1.创造阶段
2.执行阶段
var
变数会先在 创造阶段 被建立,进入执行阶段才会实际赋值,而在创造阶段中的 var
变数,他的值会是 undefined
,如这个范例:
console.log(name1) // undefined
var name1 = 'Ryder'
let
虽然也有提升概念,也同样分成:
1.创造阶段
2.执行阶段
但在创造阶段和 var
不同,let
在创造阶段不是直接显示 undefined
,他是进入一个 暂时性死区 (TDZ) 的状况,MDN 文件是这麽描述的:
The variable is in a "temporal dead zone" from the start of the block until the initialization is processed
如果我们在 暂时性死区 的状态去取得 let
变数的值,浏览器会跳错,要注意的是,不同浏览器跳出的错误讯息会不同,如下范例:
FireFox 版本
console.log(name2) // Uncaught ReferenceError: can't access lexical declaration 'name1' before initialization
let name2 = 'Ryder'
Chrome 版本
console.log(name2) //Uncaught ReferenceError: name1 is not defined
let name2 = 'Ryder'
上面有提到到 let
、 const
是根据 { ... }
来区分作用域的,这边要提一点的是 var
全域建立时,会是挂在 window 下。
而使用 let
、 const
在全域建立变数时,他并不会挂在 window 下,但我们若直接呼叫变数,他也会正确显示,如范例
var name1= 'Ryder'
let name2 = 'Ryder'
window.name1 // 'Ryder'
window.name2 // undefined
name1 // 'Ryder'
name2 // 'Ryder'
这个原因是出在全域执行环境(Global space) 上面,首先这个全域执行环境其实是由两个环境所组成的
因此全域执行环境(Global space) 其实是一个由双环境组成的东西,一般来说我们是看不到 Declare Env 的。
所以 var
其实是基於 ObjectEnv 宣告并加入到 Declare Env,而 let
、const
则是只会宣告在 Declare Env 中,这也就是为什麽我们无法在 Window 上面看到由 let
、const
宣告的变数但却又可以正常取得到值的原因。
继昨天的实作练习,有相机,会执行以下的程序码: 令 vc 为 UIImagePickerContro...
24 - Design Pattern(4) - Calculator Calculator 的 d...
Swift 游戏示意 Swift 游戏纪录 最後一个功能是游戏纪录 修改一下Player.swift...
前言 这篇的讲者很nice,直接讲了这篇演讲很适合给这几种人看 刚成为TL 还不是TL但你觉得你会...
前言 在安装过後,今天我们来测试 VM 的相关效能。 CPU 效能测试 我们采用一套有天梯的效能测试...