var

谨记一点:var 声明的变量永远声明在当前所在 函数 的作用域内,非函数作用域内声明还是被当做声明在所在函数内,如下伪代码:

function() {
var a = 1
if(any) {
var b = 1
console.log(a, b,) // 1, 1
} else {
console.log(a, b) // 1, undefined,注意不是not defined
}
console.log(b) // undefined
}

其中 var b = 1 被分解为:var b; b = 1,而 var b 部分被提升(hoisting,跟我读:好意思听?)到 function 里面了,明白?如下:

function() {
var a
var b
a = 1
if(any) {
b = 1
console.log(a, b,) // 1, 1
} else {
console.log(a, b) // 1, undefined,注意不是not defined
}
console.log(b) // undefined
}

与 window 的关系

在浏览器环境下,全局默认有个 window 对象,因为 var 的 hoisting 存在,会使得 var 个东西变成 window 的,这不是坏事,很多人已经习惯这么干了,比如:

var test = 1
window.test // 1
if(1) {
var test1 = 1
}
window.test1 // 1

这个好处是很方便获取变量,坏处就是容易把 window 的自带属性给覆盖了,如下:

var RegExp = '1'
window.RegExp // 1

大哥,RegExp 是很重要的对象好吗?


let

首先,let 就锁作用域了,跟 var 不同,不会 hoisting(读一遍),而且是根据代码块,而不是函数作用于,也就是说,if,for 等等都会锁作用域,如下伪代码:

function() {
let a = 1
if(any) {
let b = 1
console.log(a, b,) // 1, 1
} else {
console.log(a, b) // 1, not defined,其实这里是报错……
}
console.log(b) // not defined,其实这里是报错……
}

其次,let 不允许同作用域内重复声明,注意,同作用域,伪代码:

function() {
let a = 1
let a = 2 // 报错
if(any) {
let a = 3 // 没错,此a非彼a了,当前代码块内用到的都是这个a
}
}

暂时性死区 temporal dead zone,TDZ,看这个代码:

if(1) {
console.log(typeof a) // undefined,hoisting,ok?
var a = 1
}
if(1) {
console.log(typeof a) // 暂时性死区
let a = 1
}
console.log(typeof a) // undefined
if(1) {
let a = 1
}

var 不解释了,先解释第三个,就是常规的使用 typeof 检测变量属性,如果变量未申明,返回undefined,这是正常的;但是在 let 和 const(没错,const一样)所在作用域内,因为 let 和 const 的存在,导致其申明的变量被锁死,在申明前被调用的话,呵呵,不好意思,就算你是 typeof 大哥也没用,报错。

注意,说的是被 let 和 const 申明的才会被锁死,没被绑定的是常规处理,如下:

if(1) {
console.log(typeof jhdskfkjfhdkj) // undefined
console.log(typeof a) // 暂时性死区
let a = 1
}

与 window 的关系

没关系。

let RegExp = 1
window.RegExp // ƒ RegExp() { [native code] }
RegExp // 1

const

constant(跟我读:康斯顿~),就是不变的量,很多人容易忘记初始化,然后报错了再来添加初始值,这里脑子稍微过一下就可以记住:

假如不赋值能成功(说了假如),那就是 undefined,你没事创建个 undefined 来展示代码有多l ow 么?然后你又后面修改,但是本身人家就不能修改,所以一定需要初始化赋值,这样逻辑就通了……

恩,对了,他的作用域跟 let 一样一样的。没错,重复声明也不行。

之前说过,const 比较坑的就是,如果值是对象,对象的属性却是可以修改的……伪代码:

const a = {
b: 1
}
a = {} // 报错
a.b = 2 // 没错

暂时性死区

与 let 一样(const:喂喂喂,啥都跟 let 一样,搞得我好像它小弟一样。),但是由于 const 的不可变性,就不要想着用来搞常规循环那个啥了,这个跟 let 不一样。

常规循环就是 for(let i = 0; i < x.length; i ++) {} 这个,for in 和 for of 中 const 是可以用的,因为每次都是不同的嘛。

与 window 的关系

与那谁(let)一样。


用谁的问题

之前JS写的是尽量使用 let,恩,现在我改了,这个真不是这个书的事情……

默认使用 const,除非是一定需要变动的,则使用 let,极特殊的情况下并且你能控制 var,再考虑使用 var。