一、函数的作用域
- 函数作用域有点像单面镜(外面看不到里面,里面可以看到外面)
- 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 123
var 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); // 123
function a() {}
console.log(a); // 123
var b = function () {}
console.log(b); // function() {}
function d() {}
}
// 预编译发生在函数执行的前一刻
fn(1);
/*
1. 创建AO对象 (Activation Object)
2. 用形参和变量声明的名,作为AO对象的属性名,值统一为 undfiend
AO {
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); // 123
console.log(window.a); // undefined
}
test();
/*
GO: {
b: 123;
}
AO: {
a: undefined
}
*/
函数声明整体提升
变量声明提升
a = 100;
function demo(e) {
function e() {}
arguments[0] = 2;
console.log(e); // 2
if (a) { // a 是 undefined 所以这里 if 不会执行
var b = 123;
function c() {
// 猪都能做出来
}
}
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
/*
GO {
a: 100
f: 123
function demo() {}
}
AO {
c: undefined
a: 10
e: 2
}
*/