一、函数的作用域
- 函数作用域有点像单面镜(外面看不到里面,里面可以看到外面)
- JS的特点:
单线程
、是解释性语言
(翻译一行,执行一行)
二、预解析
JS预解析三部曲:语法解析 ⇒ 预编译 ⇒ 解释执行
JS 在执行之前会通篇扫描代码,看有没有语法语义错误(语法解析),如果没有,然后开始执行代码(预编译)
- 通篇扫描 -->
语法分析
- 通篇扫描之后开始执行 -->
预解析
test(); // 这种情况仍然会执行,就是预编译的作用function test() {console.log('a');
}// 在没有定义之前就使用结果为 undefined
console.log(a); // 能输出,是 undefined,还是因为预解析
var a = 10;// 但是这种就不行,因为变量没有定义就执行 b is not defined
console.log(b);
三、变量和函数的提升
函数声明整体提升
:不管你在哪调用函数,因为预解析会把函数提到逻辑的最前面,所以都是在函数的下面调用这个函数变量声明提升
imply global 暗示全局变量
:即任何变量,如果变量未经声明就赋值,此变量就为全局对象所有
a = 123;
console.log(a); // 123
console.log(window.a); // 123
- 一切声明的全局变量,都是 window 属性
var b = 234;
console.log(b); --> console.log(window.b); // 234
- 如果在全局作用域下访问变量,就相当于访问 window.变量名
var a = b = 123; // 顺序:先把 123 赋值给 b;再 let a 声明变量;最后把 b 赋值给 a。
// 但是这就导致了,b 归全局作用域所有
console.log(window.a, window.b); // undefiend 123var c = d = 234;
console.log(window.c, window.d); // 234 234
预编译四部曲
- 创建AO对象
- 找形参和变量声明,将变量和形参名作为AO属性名,值为 undefined
- 将实参值和形参统一
- 在函数体里面找函数声明,值赋予函数体
预编译练习 – 提升的意思就是被优先执行了
function fn(a) {console.log(a); // function a() {}var a = 123;console.log(a); // 123function a() {}console.log(a); // 123var b = function () {}console.log(b); // function() {}function d() {}
}// 预编译发生在函数执行的前一刻
fn(1);/*1. 创建AO对象 (Activation Object) 2. 用形参和变量声明的名,作为AO对象的属性名,值统一为 undfiendAO {a : undefined,b : undefined}3. 把形参和实参的值统一AO {a : 1,b : undefined}4. 在函数体里面找函数声明,赋予函数体AO {a : function a() {}, // 只有函数声明会提升,函数表达式不会提升b : undefined,d : function d() {}}5. 函数执行AO {a : 123,b : function() {},d : function d() {}}
*/
在全局下会生成一个GO对象(Global Object)
function test() {var a = b = 123;console.log(a);console.log(window.b); // 123console.log(window.a); // undefined
}
test();/*GO: {b: 123;}AO: {a: undefined}
*/
函数声明整体提升
变量声明提升
a = 100;
function demo(e) {function e() {}arguments[0] = 2;console.log(e); // 2if (a) { // a 是 undefined 所以这里 if 不会执行var b = 123;function c() {// 猪都能做出来}}var c;a = 10;var a;console.log(b); // undefinedf = 123;console.log(c); // undefinedconsole.log(a); // 10
}
var a;
demo(1);
console.log(a); // 100
console.log(f); // 123/*GO {a: 100f: 123function demo() {}}AO {c: undefineda: 10e: 2}
*/