码迷,mamicode.com
首页 > 编程语言 > 详细

个人对JavaScript预编译的理解

时间:2017-04-24 10:16:32      阅读:168      评论:0      收藏:0      [点我收藏+]

标签:代码注释   cee   置疑   als   ext   不同的   efi   解释执行   类变量   

什么是js的预编译

马上要找工作了,之前学习JS都是很基础的皮毛,作为当前最火热的语言,本人一定是要研究的,然而刚接触到预编译我就快疯了,对于一个脑子不好使的人来说真的太绕了,饶了好久也不知道有没有绕明白,所以先记载下来,以后发现有啥不对的再纠正。

首先,JS解释器在执行一段script脚本时,首先会进行预编译,将代码中声明的变量和函数进行处理,然后才会按代码顺序翻译执行,那么JS在预编译和执行阶段分别进行了些什么操作呢?网上有很多大神的帖子给了说明:

1. 在执行代码前会进行类似“预编译”的操作:首先会创建一个当前执行环境下的活动对象,并将那些用var申明的变量设置为活动对象的属性,但是此时这些变量的赋值都undefined,并将那些以function定义的函数也添加为活动对象的属性,而且它们的值正是函数的定义

2. 在解释执行阶段,遇到变量需要解析时,会首先从当前执行环境的活动对象中查找,如果没有找到而且该执行环境的拥有者有prototype属性时则会从prototype链中查找,否则将会按照作用域链查找;遇到var a = ...这样的语句时会给相应的变量进行赋值(注意:变量的赋值是在解释执行阶段完成的,如果在这之前使用变量,它的值会是undefined)

看完之后我的表情是懵逼的,内心是崩溃的,,,活动对象啊,prototype啊都是什么鬼,(原谅本人是一个小白,这些东西都不懂),最后经过自己尝试,总结了一下

1.预编译阶段,首先会将所有以var显示声明的变量,或者"变量式"函数提到最前面创建,不管他们在声明时同时进行赋值与否,预编译创建时都给他们赋值undefined;对于"定义式"函数声明,即用function声明的函数,其函数也会被提出来创建,但是创建后赋值的内容是该函数定义本身;另外,var显示声明的变量会先于定义式函数被创建

2.上述预编译结束后,js代码按照代码顺序解释执行,当遇到赋值语句时,再更改之前预编译过的变量的值,如var a = 11;在预编译阶段,a变量会被提出来创建,赋值undefined,在执行阶段,当执行到这条语句,将11赋给a

FOR INSTANCE

呐,基本就是这样,下面用几个例子详细说明一下,答案会在后边给出,可以自己先想一下结果是什么~

<script type="text/javascript">
console.log(a);
var a = 1;
console.log(fa);
fa();
function fa(){
    console.log("方法fa()");
}
console.log(fb);
fb();
var fb = function(){
    console.log("方法fb()");
}
fb();
</script>

像Java如果在一个变量被创建前使用这个变量,一定会报错,但是js在执行前经过了预编译事先创建了变量,所以不会报错;

首先进行预编译阶段,先将所有的变量和函数提到前面创建,并赋相应的初始值,上述的代码进过预编译处理等价成下面的代码形式:

<script type="text/javascript">
var a = undefined;
var fb = undefined;
function fa(){
    console.log("方法fa()");
}
console.log(a);
a = 1;
console.log(fa);
fa();
console.log(fb);
fb();
fb = function(){
    console.log("方法fb()");
}
fb();
</script>

首先,被var声明的变量首先被前置,创建,赋值,其次是定义式函数的预编译处理;当预编译结束,进入执行阶段,从上往下顺序执行:

1)遇到了第一个console.log(a),由于事先经过了预编译创建了a变量,所以输出undefined;

2)再向下顺序执行,遇到了a=1赋值语句,此时将1赋值给了a;

3)继续,console.log(fa),fa是定义式函数,预编译赋值内容为函数的定义,输出

function fa(){

  console.log("方法fa()");

}

4)执行fa(),即调用了fa函数,输出 方法fa()

5)执行console.log(fb),输出undefined

6)执行fb(),报错!Uncaught TypeError: fb is not a function,因为fb当前仍然是变量,还没有执行将函数赋给fb的操作;

7)将上行代码注释,继续执行,此时才将一个函数赋值给了fb

8)再次执行fb(),输出 方法fb()

另一个例子

<script type="text/javascript">
console.log(aNumber);
var aNumber = 100;
tweak();
function tweak()  {
    var newThing = 0;
    console.log(newThing);
    newThing = aNumber;
    aNumber = 42;
    if (false)  {
        var aNumber; 
        aNumber = 123; 
    }
    console.log(aNumber);
    console.log(newThing);
}
console.log(aNumber);
</script>

首先还是要预编译,注意,此处有两个aNumber,一个是全局的,一个是在if代码段中的局部变量,全局变量的aNumber被预编译处理是毋容置疑的,然而,即使if语句不会被执行,但是预编译发现了if代码段中声明的aNumber局部变量,也会进行预编译!也就是说,预编译君照吃不误,不管你是全局变量、局部变量、执行时这个变量用得着还是用不着,只要显示的用var声明了,都会进行预编译,不过此处的两个aNumber作用域是不同的;

其次是tweak()定义式函数也会被预编译,预编译结束,进入执行阶段,下面公布作业答案~

undefined  0  42  undefined  100

可以在试一下,将代码var aNumber = 100;注释掉又会发生什么?

在执行第一句console.log(aNumber)就会报错!这是为啥?

因为全局变量被注释掉了,现在只有if代码块的aNumber被预处理创建,在作用域外调用局部变量当然不行了

总结

1)首先,JS执行脚本前会将所有的变量、函数预编译,且变量先于函数预编译

<script type="text/javascript">
console.log(fc);//输出fc方法的定义部分,如果变量和函数同名,则先预编译变量,后预编译函数,函数的声明就覆盖了变量
function fc(){
    console.log("fc方法");
}
var fc = "fc变量";
console.log(fc);//执行阶段,对fc赋值为"fc变量"
</script>

可以看到,即使fc变量的定义语句在fc函数定义语句之后,但是预编译时还是会先预编译fc变量,同名情况下,后预编译的覆盖了前面的内容

2)注意,JS中变量可以隐式创建,但是这类变量应该不会被预编译,类似下面的形式会报错;

<script type="text/javascript">
console.log(c);//Uncaught ReferenceError: c is not defined
c =5;
</script>

还有就是,在局部代码块中隐式创建的变量当做全局变量使用

3)最后,JS是按<script>代码块分块执行的,且上一个script块中的变量在下一个script中仍然适用;反之则不行,如

<script type="text/javascript">
var a = 2;
console.log(c);//Uncaught ReferenceError: c is not defined
</script>

<script type="text/javascript">
var c = 5;
console.log(a);//2
</script>

个人理解的感觉还是有些出入,有什么错误还望各位dalao指正

个人对JavaScript预编译的理解

标签:代码注释   cee   置疑   als   ext   不同的   efi   解释执行   类变量   

原文地址:http://www.cnblogs.com/qingyaxuan/p/6753063.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!