我们平时写代码的时候,尤其是初学者,很难理解为什么我们var a,打印a不报错而是undefined,又或者其他一些比如函数为什么可以随意放置啊,为什么变量会覆盖啊等等基础的问题,其实这些都是js的预解析在作怪。
JS的编译和执行
JS的解析过程分为两个阶段:预编译期(预处理、预解析、预编译)与执行期。
预编译期JS会对本代码块(script)中的所有声明的变量和函数进行处理,但需要注意的是此时处理函数的只是声明式函数,而且变量也只是进行了声明但未进行初始化以及赋值。
执行期就是在编译后的基础上开始从上到下执行脚本,遇到错误时中断
何为预解析,这个主要是我们在编写js的时候, 还未执行前,js为我们储存的数据变量,js提前将我们的代码存到了它的内存当中(个人理解,不喜勿喷,欢迎留言指教)
我们知道js写法总有一些规矩,比如,为什么变量不可前置,为什么函数可以任何地方任何时候调用,这都是有原因的
上代码理解之前,分享一下我的记忆方法
js预解析:分两步执行 。
第一步:找一些东西.(代码还没有执行。预览页面之前,写完之后)
找程序中var关键字,如果找到了提前给var定义的变量赋值undefined
找程序中的普通函数,如果找到了,函数提升,将整个函数赋值给函数名。
如果找的var的名字和函数名字相同,函数优先。
第二步: 逐行解析代码。按照上下顺序。如果碰到函数定义,忽略。
重点:函数内部同样适用于js预解析。
接下来我们在代码深入理解上方的话
console.log(a)//undefined
var a=5
console.log(a)//5
第一步,找东西,找什么,找var,找到之后提前定义变量赋值undefined,第二步逐行解析代码
var a = undefined 这是在代码执行之前js为我们定义的
这就是我们常说的变量提升
console.log(a) 所以此处的a==undefined
var a=5 直到这一步 a重新赋值 为5
console.log(a) 此处a才==5
这个是var关键字,注意只有var才有变量提升,ES6的let 是没有的
a();//1
function a(){
alert(1);
}
找程序中的普通函数,如果找到了,函数提升 ,也就是说此时js预解析给我们生成了相同的函数在最顶端,所以我们说函数可以再任何地方调用,因为它肯定是在最顶部已经声明了,所以我们再执行的时候如果碰到函数定义,忽略,因为它在最上面,我们不用关心了
接下来我们看看这句,如果找的var的名字和函数名字相同,函数优先。
console.log(a) //打印出来的是函数体本身 也就是 function a(){console.log(10)}
var a=10;
function a(){
console.log(10)
}
现在能理解了吧,什么是函数优先,注意是函数名相同啊
函数我们知道有普通函数,匿名函数,还有函数表达式,再看一个例子
alert(a);//undefined
var a=function(){
alert(2);
}
alert(a);//function(){alert(2);}
var a=100;
alert(a)//100
不是说函数优先吗?为什么是undefined 因为此处是函数表达式,它的形态其实还是var,只要找到var即可赋值undefined,下方的好理解,都是覆盖声明,现在是不是有点思路了呢
我们再看看最后一个,函数内部同样适用于js预解析。
function a(){
console.log(b); //undefined
var b=10;
console.log(b)//10
}
a()
看完是不是觉得预解析其实很简单呢?当然我一时之间写不出复杂的代码,我们找一点笔试题更深入一下
好吧 找了比较长的时间,找不到适合的题目,大多都是配合闭包 this 原型,比较复杂,还是小伙伴们多多练一下基础的,可以借鉴我的记忆方法,预解析其实很简单