在一段js代码拿过来真正一句一句运行之前,浏览器已经做了一些“准备工作”,其中就包括对变量的声明,而不是赋值。变量赋值是在赋值语句执行的时候进行的。
在谈预编译之前先说收 js 的运行过程
运行过程
1.语法编译
2.预编译(通篇扫描)
3.解释执行
语法执行:就是检查你的代码有什么低级错误 就是我们平常的编译器报错
(变量为声明就是使用会报错,只有用 typeof () 编译器不会报错)
预编译:就是在内存中开辟一段空间存放 变量和函数
解释执行:js 是一种解释性语言 编译一行执行一行,单线程的同一时间只能干一件事
关于预编译
记住两句重要的话:
- 函数声明 整体提升
- 变量 声明提升
在函数体内的预编译:
1)创建AO 对象
2)找形参和变量声明,将变量和形参名作为AO 属性名(值为:undefined)
3)将是实参和形参相统一
4)在函数体里面找函数声明,便赋予函数体
(从上往下执行 执行时不再看变量声明和函数声明)
function fn(a)
{
console.log(a); //结果:ƒ a(){}
var a=123; //执行 a=123
console.log(a); //结果:123
function a(){}; //不再看函数声明
console.log(a); //结果:123
var b=function(){}; //变量声明 不为函数声明 执行 b=ƒ a(){}
console.log(b); //结果:ƒ (){}
}
fn(1);
按照以上步骤执行(预编1~4操作 后在函数中由上至下执行)
1. 创建一个AO 对象
2. a:nudefined
b:nudefined
3. a:1
b:nudefined
4. a:function a(){};
b:nudefine
当然全局也有预编译环节 对于全局变量 ( 全局执行环境直到应用程序退出 关闭浏览器才会被销毁 )
存在一些规则:
- 任何变量未经声明直接赋值(不报错)此变量就为全局变量所有
- 全局变量上的任何变量 都归 window 所有
全局的预编译环节:
基本原则和函数的预编译环节一样 只是全局下创建GO 对象 找的是全局下的变量声明和函数声明
function text(){
var a=b=123;
console.log(b); //结果:123
console.log(window.b); //结果:123
console.log(window.a); //结果:nudefined 因为a对象不为全局变量window中找不见它
}
text();
预编译环节 如果某一变量 AO 和 GO 中都有,优先访问AO 变量中的值。