js 的局部变量和全局变量
大纲
- 如何声明局部变量和全局变量
- js 变量作用域基于特有的作用域链
- js 没有块级作用域(ES5-)
- 函数中声明的变量在整个函数中都有定义
声明局部变量和全局变量
- 全局变量——定义在函数外的变量
- 局部变量——函数内部声明的变量
var a = "global";
function getLocal() {
var a = "local";
console.log(a);
}
getLocal();
console.log(a);
local
global
a = "global";
function getLocal() {
a = "local";
console.log(a);
b = "local";
console.log(b);
}
getLocal();
console.log(a);
console.log(b);
local
local
local
local
疑问:
函数外的 a 为什么变成 local?
函数外为什么可以访问 b?
解析:
函数体内部,局部变量优先级比同名全局变量高
函数体内声明变量不使用 var,会暴露在全局上下文中,和现有变量冲突,并覆盖同名全局变量
变量作用域链
每当 js 执行时会有一个对应的执行环境被创建(每一个方法在自己独有的执行环境中执行)
执行环境中的重要部分——函数的调用对象(存储相应函数的局部变量)
函数的执行环境包含了调用对象,调用对象的属性就是函数的局部变量,每个函数在这样的执行环境中执行。函数之外的代码在另一个环境中执行,包含了全局变量。
作用域链
对象组成的列表或链
var rain = 1;
function rainMan() {
var man = 2;
function inner() {
var innerVar = 4;
console.log(rain);
}
inner();
}
rainMan();
1
解析:
- rainMain()
- man 和 inner()分别是 rainMain 定义的变量和函数
- 执行 inner()
- 寻找 rain
- 先在 inner 内部找,没找到
- 继续在 rainMain 中找,没找到
- 在全局对象找,找到,输出 1
- 若全局对象中还未找到则报错:Uncaught ReferenceError: rain is not defined
在全局的 js 执行环境中,作用域链只包含一个对象——全局对象
在函数的执行环境中,同时包含函数的调用对象
js 的函数可嵌套——每个函数执行环境的作用域链可能包含不同数目个对象
一个非嵌套的函数的执行环境中,作用域链包含这个函数的调用对象和全局对象
嵌套的函数的执行环境中,作用域链包含嵌套的每一层函数的调用对象以及全局变量
JS 没有块级作用域
function checkVariable(obj) {
var i = 0;
if (typeof obj == "object") {
var j = 0;
for (var k = 0; k < 3; k++) {
console.log(k);
}
console.log(k);
}
console.log(j);
}
checkVariable(new Object());
0
1
2
3
0
i,j,k 作用域相同,都在 checkVariable()函数内都是全局的
函数中声明的所有变量,无论在哪里声明,在整个函数中都有定义
函数中声明的变量在整个函数中都有定义(即使在声明之前)
function checkVariable() {
var a = 1;
function inner() {
a = 100;
}
inner();
console.log(a);
}
checkVariable();
100
var a = 1;
function checkVariable() {
console.log(a);
var a = 2;
console.log(a);
}
checkVariable();
undefined
2
原因:checkVariable()内部变量 a 在整个函数内部有定义(var a = 2 进行了声明)
于是在整个函数内隐藏了同名全局变量 a
相当于
var a = 1;
function checkVariable() {
var a;
console.log(a);
a = 2;
console.log(a);
}
checkVariable();
总结
js 变量的域根据方法块划分,而非 for、while、if 块(因为没有块作用域)
function checkVariable() {
console.log(i);
for (var i = 0; i < 3; i++) {
console.log(i);
}
console.log(i);
while (true) {
var j = 1;
break;
}
console.log(j);
if (true) {
var k = 1;
}
console.log(k);
}
checkVariable();
console.log(i);
console.log(j);
console.log(k);
0
1
2
3
1
1
Uncaught ReferenceError: i is not defined
js 在执行前对整个脚本做分析(包括局部变量)以确定变量是局部变量还是全局变量
var a = 1;
function checkVariable() {
console.log(a);
a = 2;
console.log(a);
var a;
console.log(a);
}
checkVariable();
console.log(a);
undefined
2
2
1
函数中声明的变量在整个函数中都有定义(即使在声明之前)
这里虽然 a 一开始未使用 var 声明,但在 js 一开始的扫描时发现后面有 var 对 a 进行声明,所以 a 不会暴露在全局,覆盖同名全局变量 a,所以函数外面的输出 1
由于 a 在函数内部后面是使用 var 声明的,所以在前面的输出中能够输出 2,此时其实 a 已经被声明了,整个函数内部是整体分析的,所以才会出现函数中的变量在声明之前被定义(a = 2)
参考:https://www.w3cplus.com/javascript/the-basics-of-variable-scope-in-javascript.html