js是单线程的语言,也是一门解析型语言,所以他有着属于自己的一种运行方式,我们所说我预编译就是js解析型语言的一种解释。
- 语言分析
在我们代码执行的时候,我们的浏览器会先将js所有需要执行的代码全面检测一遍,目的是排除低级的语法错误,检测到错误后,一个一个抛出,而不是一下子全部抛出,所以js是单线程,这也是一种编程上的同步。
什么是js的同步呢?
同步:从上往下按顺序执行的程序; 弊端:中间任何一个程序出现问题,下面代码一个都不会执行就像山间小路,一个不能走了,下面全堵住了
var a = 10 ;
var b = 20 ;
console.log(a)
console.log(c) // c 没有定义,所以报错,下面的 console.log(b) 就不会执行
console.log(b)
什么是js的异步呢?
异步(多个出口):程序的执行顺序是无序的。不会存在等待现象,谁快是先执行
就像高速公路,有多条线,但还是只有一个出口
- 预编译 (变量提升,函数声明提升 )
在我们学习预编译之前,我先给大家看一个代码:
console.log(a)
var a = 10 ;
那么大家有没有一点奇怪呢?为什么没有报错,我们上面说js是一门解析型语言,按道理来说是解析一行执行一行,那么在我们输出a的时候,a还是没有定义的,所以他应该是会报错的,这里就要说到我们的预编译环节了。
首先我们先来简单的说一下变量提升,它是属于预编译的一种,我先给大家混个眼熟,然后后面再给大家详细讲解。下面我先讲解一下简略版!这个是简略版,大家且先看看:
将所有变量提升当前作用域最顶端,赋值为undefined
将函数声明提升到作用域最顶端
当变量名与函数名重复的时候 , 变量赋值 会将函数本体覆盖
console.log(a);
var a = 10 ;
// 函数声明
function a (){
}
console.log(a);
那么下面的代码再浏览器的解析中会这样执行:
//首先将所有变量提升当前作用域最顶端,赋值为undefined
var a = undefined;
// 将函数声明提升到作用域最顶端
function a (){}// 当变量名与函数名重复的时候 , 变量赋值 会将函数本体覆盖
console.log(a);//所以a的就从一开始的undefined,变成 function a (){}
a = 10;
console.log(a); // 因为值赋是不会有提升效果,所以最后执行赋值 a = 10
这样是否就可以解决大家的困惑了呢?
我来总结一下那么就是,①变量声明提升 ②函数声明,如果有重名的就将其覆盖,说到这里我们就可以解决大部分基础性问题了,但是我们讲了就要将其讲的透彻,他为什么会是这样的呢?
下面我就为大家来详细讲解预编译!
预编译存在于函数执行的前一刻!记住了,是函数执行的前一刻,大家先别去想上面的代码,先记住我的这句话,因为上面的代码讲解是存在问题的,仅仅是为了让大家了解一下什么叫做变量提升,函数声明提升 。
首先大家先看一下这四句话:
预编译存在于函数执行的前一刻!
1 生成一个AO 对象
2 将函数体中所有变量声明和形参,作为AO对象的属性名,提升到作用域的最顶端,值为undefined
3 将实参值和形参相统一
4 在函数体中,找函数声明,函数体赋予值(只有函数声明才会提升,表达式不会!!)