JS 是一门解释性语言, 主要特点是一行一行执行代码.
但在 JS 运行前, 会先进行预编译, 下面我就来说说这个预编译的规则.
首先给大家举个例子:
- var a=123;
- console.log(a) //123
如果调换下位置
- console.log(a); //undefined
- var a=123
如果我们不定义变量
console.log(a) // 报错
为什么同样打印 a, 会有这么大的差别, 这就是预编译的作用.
首先, 先普及一个概念:
变量声明 var...
函数声明 function...
- <script>
- var a = 1;// 变量声明
- function b(y){// 函数声明
- var x = 1;
- console.log('so easy');
- };
- var c = function(){// 是变量声明而不是函数声明!!
- //...
- }
- b(100);
- </script>
页面产生边创建 GO 全局对象 (Global Object), 也就是 Windows 对象
第一个脚本文件加载
脚本加载完毕后, 分析语法是否合法
开始预编译
查找变量声明, 作为 GO 属性, 赋值 undefined
查找函数声明, 作为 GO 属性, 赋值函数体
- GO/Windows = {
- // 页面加载创建 GO 同时, 创建了 document,navigator,screen 等等属性, 此处省略
- a: undefined,
- c: undefined,
- b: function(y){
- var x = 1;
- console.log('so easy');
- }
- }
完成后开始逐行执行代码, 直到执行函数 b
- GO/Windows = {
- // 变量随着执行流得到初始化
- a: 1,
- c: function(){
- //...
- },
- b: function(y){
- var x = 1;
- console.log('so easy');
- }
- }
执行函数 b;
执行函数 b 前, 也会发生预编译:
创建 AO 活动对象 (Active Object)
查找形参和变量声明, 赋值 undefined
实参赋值给形参
查找函数声明, 赋值函数体
- // 伪代码
- AO = {
- // 创建 AO 同时, 创建了 arguments 等等属性, 此处省略
- y: 100,
- x: undefined
- }
大家要注意,
预编译阶段发生变量声明和函数声明, 没有初始化行为 (赋值), 匿名函数不参与预编译
只有在解释执行阶段才会进行变量初始化
来源: http://www.jianshu.com/p/e9cdcd2d1e7b