1.js执行三部曲
1.语法分析
程序在最开始时的时候回通篇的扫描一遍,看是否有低级的语法错误。
2.预编译
函数声明整体提升,变量 声明提升
1) 预编译前奏
-
imply global
暗示全局变量 : 即任何变量,如果变量未经声明就赋值,此变量就位全局对象所有。a = 123;
-
一切声明的全局变量,全是window 的属性
var a = 123; === window.a = 123;
function fn(a) {
console.log(a);
var a = 123;
console.log(a);
function a() {}
console.log(a);
var b = function() {}
console.log(b);
function d() {}
}
fn(1);
2) 预编译的四部曲
通过上面代码来解释预编译的步骤
AO : 执行期上下文,存储空间库
一、局部 生成的是AO
-
创建AO (执行期上下文 )对象
AO{ }
-
找形参和变量声明,将变量和参数作为AO 属性名,值为undefined
AO{ a : undefined, b : undefined }
-
将实参值和形参值统一
AO{ a : 1, b : undefined }
-
在函数体里面找函数声明,值赋予函数体
AO{ a : function a() {} b : undefined, d : function d() {} }
二、全局 生成的是 GO === window
- 创建GO 对象
- 找形参和变量声明,将变量和参数作为GO 属性名,值为undefined
- 在函数体里面找函数声明,值赋予函数体
注意: 先有GO 在有 AO
练习:
练习1
global = 100;
function fn() {
console.log(global);
global = 200;
console.log(global);
var golbal = 300;
}
fn();
var global;
运行结果: undefind 200
练习2
function test() {
console.log(b); // undefind
if(a) {
var b = 100;
}
c = 234;
console.log(c); //234
}
var a ;
a = 10;
console.log(c); //234
练习题3
function bar() {
return foo;
foo = 10;
function foo() {}
var foo = 11;
}
console.log(bar()) // function foo() {}
练习4
function bar() {
foo = 10;
function foo() {}
var foo = 11;
return foo;
}
结果 : 11
练习5
a = 100;
function demo(e) {
function e() { }
arguments[0] = 2;
console.log(e); // 2
if(a) {
var b = 123;
function c() {} //在if 中是不能放function 的
}
var c ;
a = 10;
var a;
console.log(b); // undefined
f = 123;
console.log(c); //undefined
console.log(a); //10
}
var a;
demo(1);
console.log(a); //100
console.log(f); // 123
3. 解释执行
2.作用域
[[scope]] : 每一个javascript 函数都是一个对象,对象中有些属性我们可以访问,但是有些不可以,这些属性仅提供javascript引擎存取,[[scope]] 就是其中一个。
[[scope]] : 指的就是我们所说的作用域,就是存储运行期的执期上下文集合。
作用域链 : [[scope]] 中存储的执行器上下文对象的集合,这个集合呈现链式链接,我们把这种链式链接叫做作用域链。
1、运行期上下文:
-
当函数执行时,会创建一个称为 执行期上下文的内部对象。
-
一个执行期上下文定 义了一个函数执行时的环境,函数每次执行时对 应的执行上下文都是独一无二的,所以多次调用 一个函数会导致创建多个执行上下文,
-
当函数执 行完毕,它所产生的执行上下 被销毁
2、查找变量:从作用域链的顶端依次向下查找(在谁的函数上找,则在谁的作用域链从顶端开始上找)。
实例:
下列程序的执行过程:
1.被定义时
- a函数执行
-
b定义的时候(保存的是a 的引用)
-
b执行