概念
作用域:变量可以被使用的区域
块级作用域:通过{}
包裹起来的语句块, 的区域
关于作用域,在es5
及以前只有全局作用域与函数作用域,即不存在块级作用域,如以下代码中,看似有了一个新的代码块,但是由于var
关键字是用来声明一个函数范围或全局范围的变量,所以他才不会管你写在哪呢,反正就这俩范围
<script>
{
var a = 1
}
console.log(a) // 1
</script>
上述代码相当于直接将变量a
挂载到了window
,也就是全局上,所以在之后的代码中都可以拿到
var关键字
var
在声明一个变量时有以下步骤
- 先完成所有变量的声明
- 再从上至下以此进行赋值或者其他操作
var a = 1;
var b = 2;
// 等于 如下操作-----------------------------------
var a; // undefined
var b; // undefined
a = 1;
b = 2;
注意!!!!
以上过程无论是先使用了变量还是对变量进行了赋值,结果没差
a = 1 // 不会报错
b = 2 // 不会报错
var a
console.log(b)
var b
console.log(b)
因为用var
声明的变量,他的声明总会放在其他代码执行之前,而此时如果访问了变量,它的值就为undefined
,这个过程就叫做变量提升(Hoisting)
存在问题
修改外部变量
由于var
关键字的特性,可能会在不经意间修改到外部变量,如以下代码
var a = 1
if (typeof a === "number") {
var a = 100
console.log(a) // 100
}
console.log(a) // 100
以上代码无论是在全局作用域还是函数作用域中都会产生相同的结果
修改window属性
由于var
关键字声明的全局变量会挂载到window
上,所以一个不注意就可能将window
上的属性进行修改
alert("mes") // 正常
var alert = 0
alert("mes") // alert is not a function
虽然可能性比较小,但是我觉得widow上毕竟那么多属性,万一碰巧了呢!
解决
由于var
关键字只有全局作用域与函数作用域,所以通常使用函数来避免这种作用域污染问题
中场语
现在回过头来看var
,它可真麻烦,特别是通过循环给元素或者其他绑定啥东西时,都要搞个函数才好,所以这里就把es6
的let
const
也复习了吧
let与const
这两个关键字和var
一样都是用来声明变量的,区别就在于这两个关键字声明的变量会产生块级作用域!!!!!!,这就省了之前的很多麻烦事!
let 与 const 的区别
与var
比起来,这俩就像是双胞胎兄弟一样没啥区别,但是即便是双胞胎,也总有地方不一样嘛
const
用来声明一个常量,需要在声明使就进行赋值,且一但赋值就不可以改变,当然引用类型比较特殊,只要不是直接替换掉原来的值就oklet
声明一个普通变量
let 与 var 的区别
上面复习了let
和const
的区别之后,这里就只比较let
与var
了
与开头同样的一段代码,只是将var
变成了let
{
let a = 1
}
console.log(a) // a is not defined
但是结果却报错,说 a 未定义,这就说明了此时的确产生了块级作用域!!
而且就算我们在全局声明了变量
let a = 1
console.log(a) // 1
console.log(window.a) // undefined
变量 a 也没有挂载到window上
所以我们总结一下let 与 var 的区别:
- let 声明的变量具有块级作用域
- let 声明的全局变量不会挂载到window上
注意
- let 与 const 声明的变量在声明前不能被访问
- 不存在变量提升
- 产生新问题:暂时性死区
let a = 1 console.log(a) { console.log(a) // Cannot access 'a' before initialization let a = 1 }
- let 与 const 声明的变量不能被多次声明
结束语
感觉知识倒是不复杂,就是太琐碎了,知识点太细了,我都感觉好像还有很多没总结到,想到了后面再说。
但是!!!!!!有一点我很明确了,不用 var
了