编译提升
1.ES6的import变量提升
ES6 import 会产生变量提升的现象
比如uni-app项目,main.js的测试代码:
console.log('main.js')
import App from './App'
import test from './test.js'
运行uni-app项目,控制台打印如下结果
我是test.js
main.js
打印的结果是先出现‘我是test.js’,然后再出现‘main.js’,这就是变量提升的现象。
这是因为 ES6 在语言标准层面上实现了模块功能,所以当对main.js预编译时发现关键词import后,先去加载test.js,所以先输出‘我是test.js’。
整个流程是:
2.变量对象创建过程
变量对象(Variable Object)的创建,依次经历以下几个步骤:
- 检查当前上下文的函数声明,也就是使用function关键字声明的函数。在变量对象中以函数名建立一个属性,属性值为指向该函数所在内存地址的引用。如果函数名的属性已经存在,那么该属性将会被新的引用所覆盖。
- 检查当前上下文中的变量声明,每找到一个变量声明,就在变量对象中以变量名建立一个属性,属性值为undefined。如果该变量名的属性已经存在,为了防止同名的函数被修改为undefined,则会直接跳过,原属性值不会被修改。
function
声明会比var
声明优先级更高一点。
function test() {
console.log(a);
console.log(foo());
var a = 1;
function foo() {
return 2;
}
}
test();
直接从test()的执行上下文开始理解。
// 创建过程
testEC = {
// 变量对象
VO: {},
// 作用域链
scopeChain: {}
}
// VO 为 Variable Object 的缩写,即变量对象
VO = {
arguments: {...},
foo: <foo reference> // 表示foo的地址引用
a: undefined
}
test()执行的结果是:
undefined
2
其实,上面的代码demo01.js,变成了这样的执行顺序:
function test() {
function foo() {
return 2;
}
var a;
console.log(a);
console.log(foo());
a = 1;
}
test();