执行上下文的代码会分成两个阶段进行处理:分析和执行,我们也可以叫做:
1、进入执行上下文
2、代码执行
function foo(a) {
var b = 2;
function c() {}
var d = function() {};
b = 3;
}
foo(1);
进入执行上下文后,AO是:
AO = {
arguments: {
0: 1,
length: 1
},
a: 1,
b: undefined,
c: reference to function c(){},
d: undefined
}
代码执行
在代码执行阶段,会顺序执行代码,根据代码,修改变量对象的值
还是上面的例子,当代码执行完后,这时候的 AO 是:
AO = {
arguments: {
0: 1,
length: 1
},
a: 1,
b: 3,
c: reference to function c(){},
d: reference to FunctionExpression "d"
}
第一段会报错:Uncaught ReferenceError: a is not defined。
这是因为函数中的 "a" 并没有通过 var 关键字声明,所有不会被存放在 AO 中。
变量声明提升
声明提前是在JavaScript引擎的预编译时进行,是在代码开始运行之前。
函数声明提升
1. 函数声明
function sum(num1, num2) {
return num1 + num2;
};
函数声明提升会在编译阶段把函数和函数体整体都提前到执行环境顶部,所以我们可以在函数声明之前调用这个函数
sum(10, 10); //20
function sum(num1, num2) {
return num1 + num2;
};
JavsScript 编译器在预编译的时候把代码编译:
var sum;
sum = function (num1, num2) {
return num1 + num2;
};
sum(10, 10); //20
函数声明提升>形参>变量声明提升
2. 函数表达式
函数表达式没有函数声明提升,只有定义了之后才能调用,上述代码实质上是这样的
var sum = function (num1, num2) {
return num1 + num2;
}
||
var sum;
sum = function (num1, num2) {
return num1 + num2;
}
做题:
1、
var foo = 1;
function bar () {
console.log(foo);
var foo = 10;
console.log(foo);
}
bar();
会输出 undefined 和 10
Js引擎真正的执行顺序 =>
var bar;
bar = function () {
var foo;
console.log(foo);
foo = 10;
console.log(foo);
}
var foo = 1;
bar();
2、
var foo = 1;
function bar () {
console.log(foo);
foo = 2;
}
bar();
console.log(foo);
foo = 2;//隐性全局变量,实际是全局属性
3
var foo = 1;
function bar (foo) {
console.log(foo);
foo = 234;
}
bar(123);
console.log(foo);
这里第一个foo输出的是123 通过bar(123)传进去
最后一个foo输出的是1 带有形参的函数 没有var的定义 改变的是实参 在foo=234后面输出foo的值 就会显示foo为234
4
var b = "boy";
console.log(b);
function fighting() {
console.log(a);
console.log(c);
if (a === "apple") {
a = "Alice";
} else {
a = "Ada";
}
console.log(a);
var a = "Andy";
middle();
function middle() {
console.log(c++);
var c = 100;
console.log(++c);
small();
function small() {
console.log(a);
}
}
var c = (a = 88);
function bottom() {
console.log(this.b);
b = "baby";
console.log(b);
}
bottom();
}
fighting();
console.log(b);
这是道综合题
顺序是下面那样的 =>
var b = "boy";
console.log(b); //boy
function fighting() {
function middle() {
function small() {
console.log(a);//Andy
}
var c ;
console.log(c++); //NaN
c = 100;
console.log(++c);//101
small();
}
function bottom() {
console.log(this.b); //boy
b = "baby"; //隐形全局变量
console.log(b);//baby
}
var a,c;
console.log(a);//undefined
console.log(c);//undefined
if (a === "apple") {
a = "Alice";
} else {
a = "Ada";
}
console.log(a);//Ada
a = "Andy";
middle();
c = (a = 88);
bottom();
}
fighting();
console.log(b); //boy × => baby
这里有几个注意的点
- 定义c后 没有复制 直接输出c++ 输出的是NaN(不是Number类型
- bottom函数中 b="baby"是隐形全局变量 是定义到了全局