js 预编译
js 运行代码的时候分为几个步骤:语法分析 ==》预编译 ==》解释执行
语法解析:通篇扫描代码,查看语法是否出错
解释执行:读一行 - 解释一行 - 执行一行
预编译执行的操作:
// 假设之前并没有定义a
console.log(a);
打印结果:Uncaught ReferenceError: a is not defined
这个大家应该都知道:在变量未定义时就对变量进行访问就会报错(typeof 列外)
再看一个例子:
// 假设之前并没有定义变量a
console.log(a); var a = 123; console.log(a);
看上面代码会打印什么?会不会报错?
打印结果:
undefined
123
为什么这个没有报错:因为在预编译的时候对变量进行了提升即变量提升。 定义的变量的声明(var a ;)被提到了代码块的最前面,变量的赋值操作(a = 123)没有变化。
所以被编译后就相当于
// 假设之前没有定义变量a
var a; console.log(a); a = 123; console.log(a);
看下面这个例子:
// 假设之前没有定义test
console.log(test); var test = 123; function test () { } console.log(test);
打印结果:
function test () {}
123
为什么第二行的输出的不是undefined 了?执行步骤是什么样子的?
因为函数声明在编译的时候也会进行提升,叫做函数提升。
执行步骤:
1、变量提升:var test; 提升到最前面。此时test = undefined;
2、函数提升:function test () {}; 提升到最前面并覆盖var test; 的声明。所以第二行打印function test () {}; 此时test = function test () {}
3、进行赋值操作 test = 123; 此时test = 123;
function test (test) {
console.log(test); // function test(){var a = 789}
var test = 123;
function test () {
var a = 789;
};
console.log(test) ; // 123
} test(456);
Why?
变量提升和函数提升是如何实现的?
预编译执行步骤:
(a) 函数内
1、在代码定义之后执行之前生成活动对象AO(Activation Object ) 空对象{}
2、查找函数体内的形参和变量,定义为AO的属性,赋值为undefined;
3、将实参跟形参统一,即把实参赋值给AO[形参]
4、查找函数里的函数声明,将函数声明赋值给AO 即 AO[函数名] = 函数
(b) 全局
1、在代码定义之后执行之前生成全局环境对象GO(Global variable Object ) 空对象{}
2、查找变量,定义为GO的属性,赋值为undefined;
3、查找函数声明,将函数声明赋值给GO 即 GO[函数名] = 函数;
以上面的例子分析预编译过程:
function test (test) {
console.log(test); // function test(){var a = 789}
var test = 123;
function test () {
var a = 789;
};
console.log(test) ; // 123
} test(456); var a = 111; /** 全局 **/
// 第一步:创建GO
// GO{};
// 第二步:查找变量定义为GO的属性,赋值为undefined;
// GO{
// a: undefined
// };
// 第三步:将函数声明赋值给GO
// GO{
// a: undefined,
// test: function test(test) {...}
// } /** function test(test){...} 函数内 **/
// 第一步: 创建AO
// AO {}
// 第二步: 查找形参和变量,定义为AO的属性, 赋值为undefined;
// AO {
// test: undefined
// }
// 第三步: 形参和实参统一
// AO {
// test: 456
// }
// 第四步:将函数声明给AO
// AO {
// test: function test() { var a = 789 }
// }
之后就是一步一步的执行代码了
function test (test) {
console.log(test); // function test(){var a = 789}
var test = 123;
function test () {
var a = 789;
};
console.log(test) ; // 123
} test(456); var a = 111; // test(456); 进入到function test (test) {...} 内部
// console.log(test); // 打印 function test(){var a = 789}
// var test = 123; 由于 test 变量的声明已经提升,所以这句只执行 test = 123; 即AO[test] = 123
// AO {
// test: 123
// }
// function test() {var a = 789} 已经提升
// console.log(test) //打印 123
// 退出function test (test) {...} 销毁AO
// var a = 111; 由于 a 变量已经提升,这句只执行赋值 a = 111; 即 GO[a] = 111;
// GO{
// a: 111,
// test: function test(test) {...}
// } // 当页面销毁时销毁GO
最新文章
- SQLServer地址搜索性能优化例子
- pdo 整套类的封装,保存修改查询
- MySQL7:视图
- GridControl
- EF 7 Code First
- WCF发布后远程访问的域名解析问题
- ContentProvider的使用
- Sping IOC
- python函数说明内容格式错误
- [Awson原创]修水渠(canal)
- css清除默认样式,stylus学习
- oracle储存过程学习笔记
- spring 事务的七中传播行为五中隔离
- MySQL 出现 Host is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'
- ES9新特性
- Curator之Recipes之锁
- iOS - 直播总结(理论到实践)
- web中的安全编码
- 在Loadrunner中如何用system函数执行系统命令
- mac下为什么光标按方向键只能一个字一个字地蹦
热门文章
- redis端口6379的由来
- Visual Studio Code | 报错 command 'markdown.extension.onBackspaceKey' not found
- springboot之整合基本的jdbc并操作Mysql数据库
- 有基因ID或者基因名,如何拿到对应的KEGG通路图?
- Windows玩转Kubernetes系列3-Centos安装K8S
- 分享数百个 HT 工业互联网 2D 3D 可视化应用案例之 2019 篇
- 隐马尔可夫(HMM)/感知机/条件随机场(CRF)----词性标注
- SVN本地服务器搭建及在Eclipse中的应用
- 【大白话系列】MySQL 学习总结 之 初步了解 MySQL Server 的 binlog 组件
- Codeforces_478_C