暗示全局变量
什么是暗示全局变量(imply global variable)呢?
在JavaScript
中所有的变量都归window
对象所有。如下:
var a = 1;
b = 2;
// 可以理解成这样
// window = {
// a: 1,
// b: 2
// }
在JavaScript
中,如果不使用var
关键字进行变量声明,那么这个变量就是「全局变量」。
function test() {
var a = b = 1;
c = 2;
}
test()
console.log(b); // 1
console.log(c); // 2
console.log(a); // error,a 不是全局变量
预编译
因为JavaScript
是解释型开发语言,所以它的执行步骤是:
- 检查通篇的语法错误
- 预编译
- 解释一行执行一行
console.log(a); // error,检查语法错误
在「预编译」的过程中,函数声明会被整体提升,所以你在函数声明前调用函数还是函数声明后调用函数是一样的
test(); // 1
function test() {
console.log(1);
}
test(); // 1
console.log(a); // function()
function a(){}
在声明变量的时候只有变量的提升的,赋值是不会提升的。
console.log(a); // undefind
var a = 1;
var b = 3; // 变量声明且赋值
console.log(c); // Error,预编译的过程中发现 c 没有定义
// 以上代码在预编译的过程中其实值这样的
// 在预编译时我们不看赋值,只把变量的声明提升,因此若在赋值前打印会提示 undefined
var a;
var b;
a = 1;
b = 3;
那么到底什么是预编译???
预编译就是全局代码和函数执行之前执行的步骤。
预编译的执行过程可以分为三步:
- 寻找函数的形参和变量声明,赋值为
undefind
- 将实参的值赋值给形参
- 找函数声明且赋值函数体
我更愿意把预编译理解成五步:
- 执行函数
- 变量赋值
我们先来看函数执行上下文。Activation Object
活跃对象,简称AO
,或者「函数上下文」。
function test(a) {
console.log(a); // funtion
var a = 1;
console.log(a); // 1
function a() {}
console.log(a) // 1
var b = function () {};
console.log(b); // function
function d() {}
}
test(2);
// 以上函数执行的预编译过程是
// 0、创建 AO 对象
// 1、寻找函数形参和变量声明,所以我们能找到形参 a 和变量声明 b
AO = {
a: undefind,
b: undefind
}
// 2、实参数据赋值给形参
AO = {
a: undefind => 2,
b: undefind
}
// 3、寻找函数声明且赋值函数体,我们能看到 a 和 d 都是函数声明
AO = {
a: undefind => 2 => function(),
b: undefind,
d: function()
}
// 4、执行函数
// 5、变量赋值
// 第 2 行执行的时候,a 是 function() ,所以打印 function
// 第 3 行,a 被赋值为 1
// 第 4 行,打印 a 为 1
// 第 5 行,a 在预编译阶段已经赋值为 function 所以这行忽略
// 第 6 行,a 无变化,所以打印 1
// 第 7 行,b 赋值为 function()
// 第 8 行,打印 b 为 function()
// 第 9 行,d 在预编译阶段赋值为 function
以上就是一个函数执行上下文的一个全过程。
Global Object
全局上下文,简称GO
,和AO
执行过程是一样的,只不过GO
不存在函数实参对应过程。
var a = 1;
function a() {}
console.log(a);
// 以上代码的执行过程
// 0、创建 GO 对象
// 1、寻找变量声明
GO = {
a: undedfind
}
// 2、寻找函数声明
GO = {
a: undedfind => function()
}
// 3、执行代码
// 4、变量赋值
// 第 1 行,把 a 赋值为 1
// 第 2 行,预编译阶段已经执行所以忽略
// 第 3 行,打印 a 为 1
下面再看几个例子:
function test() {
var a = b = 1;
console.log(a); //
}
// 自己不存在的会去GO对象中寻找
GO = {
b: undefind => 1
}
AO = {
a: undefind => GO.b => 1
}
var b = 3;
console.log(a); // function
function a(a) {
console.log(a); // function
var a = 2;
console.log(a); // 2
function a() {}
var b = 5;
console.log(b); // 5
}
a(1);
// 执行过程
GO = {
b: undefind => 3
a: function
}
AO = {
a: undefind => 1 => function => 2
b: undefind => 5
}
function test() {
console.log(b); // undefind
if (a) { // if 语句执行的时候才会判断,这里看的是预编译
var b = 2;
}
c = 3;
console.log(c); // 3
}
var a;
test();
a = 1;
console.log(a); // 1
// 执行过程
GO = {
a: undenfind => 1
test: function
c: undefind => 3
}
AO = {
b: undefind
}