听小野森森的预编译,收货颇丰,之前完全没有了解过。遇到这方面的面试题,特别的头大,只知道变量和函数会提升。这次终于了解了捕鱼的技术,而不是鱼。但是现在很少用var了,基本上都是用const、let了,乐趣少了些,哈哈哈。
JavaScript 在执行脚本的时候,首先会通篇的检查是否有语法错误,如果有,报错,不再继续执行;当没有语法错误时,则进行预编译,最后解释一行执行一行。
声明提升
- 函数声明整体会被提升,函数内部的代码不会进行预编译,函数执行的前一步时,才会对函数内部的代码进行预编译
函数 test 被提升到顶部,所以函数可以在其声明之前被调用
test();
function test(){
console.log('test');
}
- var 声明的变量会被提升,只会提升变量名,运行到赋值那一行才会进行赋值,声明的变量挂载到当前的作用域下
- 非 var 声明的变量,是赋值语句,如果当前作用域下没有声明过该变量(函数声明或者形参),则挂载在window对象上
var 声明的变量a会被提升到顶部,值为 undefined,运行到赋值那一行,它的值才是100。变量 b 不会被提升,赋值之前使用 b 报错,赋值之后则不会。
// console.log(a, b);
console.log(a);
var a = 100;
b = 200;
console.log(a, b);
函数内部声明的变量 b 保存在当前作用域内,当前作用域下没有声明过变量 c , 则挂载在 window 对象上。
function test() {
var b = 20;
c = 20
}
test();
console.log(c);
函数内部通过形参声明变量
function test(c) {
var b = 20;
c = 20
console.log(c); // 20
}
test();
console.log(c); // Uncaught ReferenceError: c is not defined
通过函数声明的方式声明变量
function test(c) {
var b = 20;
c = 20
function c() { };
console.log(c); // 20
}
test();
console.log(c); // Uncaught ReferenceError: c is not defined
AO对象
当函数执行的前一步时,JavaScript引擎才会对函数进行预编译,会创建AO对象, Activation Object 也就是函数上下文对象。
具体过程
function test(a){
console.log(a); //func a
var a = 1;
console.log(a); // 1
function a(){};
console.log(a); // a
var b = function(){};
console.log(b); // func b
function d(){};
}
test(100);
- 第一步、创建AO对象,就是一个{};
AO = {}
- 第二步,寻找形参和var变量声明
AO = {
a: undefined
b: undefined
}
- 第三步,把实参赋值给形参
AO = {
a: 100
b: undefined
}
- 第四步,寻找函数声明
AO = {
a: function a(){},
b: undefined,
d: function d(){};
}
- 第五步,执行函数,忽略var 声明和函数声明,遇到赋值语句,会覆盖初始化值
AO = {
a: function a(){},
b: function(){},
d: function d(){};
}
GO对象
GO 对象就是 Global Object 全局上下文,和 AO 对象类型。
分析具体过程
var a = 100;
function a(){
console.log(2);
}
- 第一步、创建 GO 对象
GO = {}
- 第二部、寻找变量声明
AO = {
a: undefined
}
- 第三步、寻找函数声明
AO = {
a: function a(){}
}
- 第四步、执行语句、遇到赋值语句,会覆盖初始化值
面试题
function test(a,b){
console.log(a); // 1
c = 0;
var c ;
a = 5;
b = 6;
console.log(b); // 6
function b(){};
function d(){}
console.log(b); // 6
}
test(1);
具体过程
GO = {
test: function test(){},
}
// test函数执行
// 寻找形参、变量声明
AO = {
a: undefined,
b: undefined,
c: undefined,
}
// 实参赋值给形参
AO = {
a: 1,
b: undefined,
c: undefined,
}
// 寻找函数声明
AO = {
a: 1,
b: function b(){},
c: undefined,
d: function d(){},
}
// 执行代码,赋值
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。