# 关键字var
前言
var
声明的变量会被提升
# 1.块级作用域
作用域就是一个变量作用的范围。也就是你声明一个变量以后,这个变量可以在哪些范围下使用,var 声明的变量 只有全局作用域
和函数作用域
var
没有块级作用域
(封闭作用域),定义后在当前的闭包中都可以访问,如果变量名重复,就会覆盖前面定义的变量,并且也有可能被其他人修改
语句后面的代码块{}
中var
声明的变量的作用域就不是函数作用域
- 1.同步执行
if (true) {
var a = "a"
}
console.log(a) // a为全局作用域下的变量
1
2
3
4
2
3
4
- 2.异步执行
var
覆盖之前定义的变量,同步代码执行完毕 i
为 3,再执行异步代码
for (var i = 0; i < 3; i++) {
setTimeout(() => {
alert(i) // 三次弹窗,都是 3
}, 0)
}
1
2
3
4
5
2
3
4
5
# 2.全局作用域
var
声明变量是在函数最外部,那么此变量作用域就是全局作用域下的变量,全局都能使用这个变量
var 不支持封闭作用域,如果不是在函数里声明的变量会声明到全局作用域(window)上,在代码块中的变量外部也可以访问,而且还是放到全局作用域上面
for (var i = 0; i < 3; i++) {
console.log(i)
}
console.log(i)
console.log(window.i)
// 0
// 1
// 2
// 3
// 3
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
解决方式一:使用自执行函数将其声明在函数作用域内
;(function () {
for (var i = 0; i < 3; i++) {
console.log(i)
}
})()
console.log(i)
console.log(window.i)
// 0
// 1
// 2
// Uncaught ReferenceError: i is not defined
// at <anonymous>:6:13
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
问题二: 异步的问题
由于代码块中的代码是异步的,会被放到异步队列中执行,当代码把任务队列中的同步代码执行完毕后 i 赋值为 3,然后执行异步队列中的代码,拿到的 i 是 3
for (var i = 0; i < 3; i++) {
setTimeout(function () {
console.log(i)
}, 1000)
}
// 3
// 3
// 3
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
解决方式
解决异步的问题
for (var i = 0; i < 3; i++) {
;(function (i) {
setTimeout(function () {
console.log(i)
}, 1000)
})(i)
}
// 0
// 1
// 2
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 2.1 全局变量
- 在 if 或者 for 循环中声明的变量会变成全局变量
for (var i = 0; i <= 5; i++) {
console.log("hello")
}
console.log(i) //5
1
2
3
4
2
3
4
# 2.2 变量覆盖
var a = 1
function fn() {
console.log(a)
if (false) {
var a = 2
}
}
fn() //undefined
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 3.函数作用域
var
声明的变量是在函数代码块{}
中声明的,那么此变量的作用域就是函数作用域下的变量,只能被此函数和函数内部的函数使用
← 八.调试方法 关键字function →