Appearance
作用域变量
作用域:就是变量的作用范围。也就是你声明一个变量以后,这个变量可以在什么场合下使用。以前的 JavaScript 只有全局作用域,和函数作用域。
var 的问题
var 没有块级作用域,定义后在当前包中都都可以访问,如果变量名重复,就会覆盖前面定义的变量,并且很可以被他人修改。
js
if(false){
var a = "a"; //期望a是某一个值
}
console.log(a); // 'a'
1
2
3
4
2
3
4
var 在 for 循环标记变量共享,一般在循环中会使用的 i 会被共享,其本质也是由于没有块级作用域造成的
js
for (var i = 0; i < 3; i++) {
setTimeout(function () {
alert(i);
}, 0);
}
// 结果就是 弹窗三次 3
for ( i = 0; i < 3; i++) {
setTimeout(function () {
alert(i);
}, 0);
}
// 结果就是 弹窗三次 0-2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let 声明变量
- 不存在变量提升,存在暂时性死区:变量声明之前不能使用
js
// 存在暂时性死区
if(ture){
let name = 'wjh'
}
consloe.log('name'); // ReferenceError: name is not defined
1
2
3
4
5
2
3
4
5
- 不允许在相同作用域内(使用 var, let, const,函数声明)重复声明同一个变量,不能在函数内部使用 let 重新声明参数
js
if(ture){
let a = 1;
let a = 2; // Identifier 'a'
}
1
2
3
4
2
3
4
- let 声明的变量绑定在其块作用域上,不受外部得影物响
js
// 嵌套循环不会相互影响
for (let i = 0; i < 3; i++) {
console.log("out", i);
for (let i = 0; i < 2; i++) {
console.log("in", i);
}
}
// 结果 out 0 in 0 in 1 out 1 in 0 in 1 out 2 in 0 in 1
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- let 声明的变量没有挂载到 window 上,不能通过 window。属性的形式访问
js
if(false){
let name = 'wjh'
}
console.log(window.name); // undefined
1
2
3
4
2
3
4
const 常量
必须在声明时初始化
并且一旦声明,常量的值不能修改不能重复定义
js
const MY_NAME = 'wjw';
MY_NAME = 'wjw2'; // Assignment to constant variable
1
2
2
- 不存在变量提升存在暂时性死区
js
if(false){
const name = 'wjh'
}
consloe.log(name); // ReferenceError: name is not defined
1
2
3
4
2
3
4
- 实际上并不是变量值不能改动,而是变量指向的内存地址不得改动本质 Object.Freeze 使常量(对象,数组)不可变:对象冻结
js
const obj = {a:1};
obj.a = 2
consloe.log(obj.a); // 2
Object.freeze(obj)
obj.a = 3
consloe.log(obj.a); // 2
1
2
3
4
5
6
2
3
4
5
6
- 不同的块级作用域可以多次定义
js
const A = "0";
{
const A = "A";
console.log(A)
}
{
const A = "B";
console.log(A)
}
console.log(A)
// 结果 A B 0
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12