JavaScript执行机制之执行顺序

 转发自:https://blog.csdn.net/u014346301/article/details/52250008

JavaScript是一种描述型的脚本语言,不同于C#或者java,它不需要进行编译成中间语言,而是由浏览器动态的解析和执行。今天我们就来说一个JavaScript是如何解析的,它的执行顺序是怎么样的?在此之前,我们先来了解几个术语。

一、代码块

       JavaScript中的代码块是指由<Script>标签分割的代码块。例如:

<script>
console.log("这是代码块一");
</script>

<script>
console.log("这是代码块二");
</script>

       JavaScript是按照代码块来进行编译和执行,代码块之间相互独立,但是变量和方法共享。如下:

<script>
var str = "Hello JavaScript";
console.log(str_test);  //执行结果: 报错 str_test is not defined 。 没有定义这个变量
</script>

<script>
console.log(str);   //输出Hello JavaScript,因为在代码块一中定义了str
</script>

       上面的代码块一中运行报错,但是不影响代码块二中代码的执行,这就是代码块的独立性,代码块二能调用代码块一中的变量,这是代码块中的共享性。

二、声明式函数与赋值式函数

       JavaScript中的函数定义分为两种:声明式函数和赋值式函数。如下:

<script>
function Fn(){
    //声明式函数
}
var Fn = function(){
    //赋值式函数
}
</script>

       声明式函数和赋值式函数的区别在于:在js预编译时期,声明式函数会先被提取出来执行,然后再按顺序执行js代码。

三、预编译期与执行期

       事实上,js解析过程分为两个阶段:预编译期(预处理)与执行期。
       预编译期js会对本地代码块中所有声明的变量和函数进行处理,需要注意的是这里处理的函数只是声明式函数,而且对于所有的变量只进行了声明,并未进行初始化和赋值。

<script>
Fn();   //执行结果 :声明式函数二 。如果声明了两个同名函数,则后面的函数会覆盖前的函数
//函数一
function Fn(){
    console.log("声明式函数一");
}
//函数二
function Fn(){
    console.log("声明式函数二");
}
</script>

//----------分割线-------------//
<script>
Fns();  //执行结果:声明式函数 。 可以看出声明式函数在预编译阶段被执行,而赋值式函数并没有在预编译阶段被执行
//声明式函数
function Fns(){
    console.log("声明式函数");
}
//赋值式函数
var Fns = function(){
    console.log("赋值式函数");
}
Fns();  //执行结果:赋值式函数 。 可以看出在执行阶段赋值式函数被执行,并覆盖了同名的声明式函数
</script>


//--------分割线-------//
<script>
console.log(str_1);     //执行结果:undefined 。 可以看出函数预编译阶段声明了str_1这个变量,但是并没有为他赋值。
var str_1 = "Hello JavaScript";
</script>
  •  

下面来看一个例子:

<script>
Fn_1();     //执行结果:报错 Fn_1 is not defined 。 没有定义这个函数
</script>
<script>
function Fn_1(){
    console.log("这是在代码块二中定义的函数");
}
</script>

        上面这段代码中代码块一输出是报错了,没有定义Fn_1这个函数,但是在代码块二中我们已经定义这个函数了,这是为什么呢。这里有一点要特别注意一下,我们上面说JS是按照代码块的顺序来执行的,完整的说是按照代码块来进行预编译和执行的,也就是说预编译只预编译到这个代码块中声明的变量和函数,然后开始执行这个代码块。而对于后面还未加载的代码块,是没有办法预处理的,这也是边编译变处理的核心所在。

        理解了上面几个术语和例子,JS的运行机制就基本上清楚了,下面我们来总结一下流程:

step 1.读入第一个代码块。
step 2.做语法分析,有错则报语法错误(比如括号不匹配等),如果后面还有代码段就跳转到step 5。
step 3.对var定义的变量和function定义的函数进行预编译处理(这里永远不会报错,因为JS只解析正确的声明)。
step 4.执行代码段,有错则报错。
step 5.如果还有下一个代码段,则读入下一个代码段,执行step 2。
step 6.结束。

      而根据HTML文档的加载顺序,需要在页面元素渲染前加载的文件应该放在<body>元素的前面,需要在页面渲染完成后加载的文件放在</body>元素的后面,body标签的onload事件是最后执行的。

猜你喜欢

转载自blog.csdn.net/illikang/article/details/81808845