从var func=function 和 function func()区别谈Javascript的预解析机制

var func=function 和 function func()在意义上没有任何不同,但其解释优先级不同:
后者会先于同一语句级的其他语句。

即:

{
 var k = xx();
 function xx(){return 5;}
}

不会出错,

{
 var k = xx();
 var xx = function(){return 5;}
}

则会出错。

为什么会这样呢?这就要引出javascript中的预解析机制来解释了。

JavaScript解析过程分为两个阶段,一个是编译阶段,另外一个就是执行阶段。

  * 编译阶段

         编译阶段就是我们常说的JavaScript预解析(预处理)阶段,在这个阶段JavaScript解释器将完成把JavaScript脚本代码转换到字节码。

  * 执行阶段

    在编译阶段JavaScript解释器借助执行环境把字节码生成机械码,并顺序执行。

编译阶段(预解析阶段)做什么操作?

  * var , function声明的变量提升

    首先,创建一个当前执行环境下的活动对象,然后将用 var 声明的变量设置为活动对象的属性(也就是将其添加到活动对象当中)并将其赋值为undefined,然后将function 定义的函数 也添加到活动对象当中。

1 if( false ){
2     var aa = 20;
3     var bb = 30;
4 }
5
6 function AA(){};
7 function BB(){};
8
9 //var定义的aa,bb以及function定义的AA(),BB()都会被变量提升到window对象下面

 * 函数声明与函数表达式在预解析的区别

    首先,我们知道解析器会对function定义的函数(也就是函数声明)在代码开始执行之前对其实行函数声明提升(function declaration hoisting),所以在函数声明之前调用该函数是不会在执行期间报错,但是函数表达式不同,函数表达式用 var 声明,也就是说解析器会对其变量提升,并对其赋值为undefined,然后在执行期间,等到执行到该var 变量的时候再将其变量指向一个function函数,所以在函数表达式之前执行该函数是会报错的。

1 AA();
2 function AA(){};
3
4 BB();
5 var BB = function(){};
6
7 //AA();不会报错,因为是以function的变量提升,BB()会报错,因为是以var的变量提升,到其相当于 BB(); var BB = undefined; BB = function(){};

  * function 覆盖

    若定义了两个同名的函数,则在预解析期间后面一个会覆盖签名一个

1 AA();   // 输出 I am AA_2;
2 function AA(){
3    console.log(‘I am AA_1‘);
4 };
5
6 AA();  // 输出 I am AA_2;
7 function AA(){
8   console.log(‘I am AA_2‘);
9 }

  * 预解析把变量或函数解析到其运行时的环境中

    解析器将变量提升并不是将所有的变量都提升到window对象下面,其提升的原则是提升到变量运行的环境中去。

 1 aa = "I am aa";
 2 (function(){
 3     console.log(aa);  // 输出 aa 是 undefined
 4     var aa = "I am aa in a function";
 5     console.log(aa);  //输出 aa 是 I am aa in a function
 6 })();
 7
 8 // 这里 aa 被变量提升,但是aa 没有被变量提升到 window下面,而是被提升到其运行的环境 (function(){ })() 中去,也就是等同于
 9
10 // aa =  "I am aa";
11 //(function(){
12 //    var aa;
13 //    console.log(aa);  // 输出 aa 是 undefined
14 //    aa = "I am aa in a function";
15 //    console.log(aa);  //输出 aa 是 I am aa in a function
16 //})();
17
18
19
20 // 下面代码等同于上面,目的是为了若看不懂上面,则可看下面。
21 aa = "I am aa";
22 function AA(){
23     console.log(aa);
24     var aa = "I am aa in a function";
25     console.log(aa);
26 }
27 AA();

  * JavaScript“预解析”分段进行

    所谓分段进行是按照<script>标签来分块进行预解析

 1 <script>
 2 AA();  // 输出 AA2;
 3 function AA(){
 4    console.log(‘AA1‘);
 5 }
 6
 7 function AA(){
 8    console.log(‘AA2‘);
 9 }
10 </script>
11
12
13 <script>
14 function AA(){
15    console.log(‘AA3‘);
16 }
17 </script>
18
19 //上面例子说明function函数声明是分块的,然而至于var变量的提升经过反复验证是不分块的( 此处如有不同意见请指教 )。

  * var 变量提升以及 function 函数声明提升

    该点是对函数声明以及函数表达式进一步的说明,其实前面函数声明和函数表达式在预解析的不同表现,其主要的原因就是 var 和 function 两者不同的提升。这个问题从解析阶段到运行阶段来说明。首先,在解析阶段 var 后面的 AA 会被提升然后 AA 被定义为undefined,BB 也会被提升,而BB被提升后的内容就是整个 function 里面的内容,其实从浏览器的控制台我们可以看出一二。然后,整个解析过程完了就到了运行阶段,在运行阶段期间,当读到 AA() 的时候,其实就是将 AA 这个变量指向function(){}这个函数然后调用,而到了 BB() 的时候,就会从之前声明的函数中去查找该早已经声明的函数,然后直接调用。

 1 var AA = function(){
 2    console.log(‘ AA_ 1 ‘);
 3 }
 4
 5 AA(); // 输出 AA_1
 6
 7
 8 function AA(){
 9    console.log(‘ AA_2 ‘);
10 }
11 AA(); //输出 AA_2
12
13 //这个例子就很好说明了 var 在运行阶段动态内建,而 function 在预解析阶段静态建立。

时间: 2024-10-25 21:56:19

从var func=function 和 function func()区别谈Javascript的预解析机制的相关文章

javascript中function和object的区别,以及javascript如何实现面向对象的编程思想.

1 <!DOCTYPE html> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 5 <title></title> 6 <script language="

(function ( ){})( ) 与 (function ( ){}( )) 有什么区别?

js立即执行函数: (function ( ){})( ) 与 (function ( ){}( )) 有什么区别? 转自:http://www.jb51.net/article/75089.htm 这篇文章主要介绍了js立即执行函数: (function ( ){})( ) 与 (function ( ){}( )) 有什么区别,需要的朋友可以参考下 没有区别. 你需要明白 IIFE 的原理,我简单说一下: 复制代码 代码如下: function foo() {...}     // 这是定义

闭包(Closure)和匿名函数(Anonymous function)/lambda表达式的区别

闭包(Closure)和匿名函数(Anonymous function)/lambda表达式的区别 函数最常见的形式是具名函数(named function): function foo(){ console.log("named function") } foo() 不过也可以将函数视作数据赋值给变量,这样的函数可以没有名字: nameless = function(){ console.log("anonymouse function") } nameless(

jQuery(function(){})与(function(){})(jQuery)的区别

开发jQuery插件时总结的一些经验分享一下. 一.先看 jQuery(function(){ }); 全写为 jQuery(document).ready(function(){       }); 意义为在DOM加载完毕后执行了ready()方法. 二.再看 (function(){ })(jQuery): 其实际上是执行()(para)匿名方法,只不过是传递了jQuery对象. 三.总结 jQuery(function(){ });用于存放操作DOM对象的代码,执行其中代码时DOM对象已存

function,new function,Function,new Function 之间的区别

测试一: var fud01 = function()  { var temp = 100; this.temp = 200; return temp + this.temp; } alert(typeof(fud01)); alert(fud01()); 运行结果: function 300 最普通的function使用方式,定一个JavaScript函数.在大扩号内的变量作用域中,this指代fud01的所有者. 测试二: var fud02 = new function() { var t

jQuery中$(function(){})与(function($){})(jQuery)、$(document).ready(function(){})等的区别详细讲解 ----转载

1.(function($) {-})(jQuery); 1).原理: 这实际上是匿名函数,如下: function(arg){-} 这就定义了一个匿名函数,参数为arg 而调用函数时,是在函数后面写上括号和实参的,由于操作符的优先级,函数本身也需要用括号,即: (function(arg){-})(param) 这就相当于定义了一个参数为arg的匿名函数,并且将param作为参数来调用这个匿名函数 而(function($){-})(jquery)则是一样的,之所以只在形参使用$,是为了不与其

$(document).ready(){}、$(fucntion(){})、(function(){})(jQuery)onload()的区别

 1.首先说JQuery的几个写法  $(function(){     //do someting   });   $(document).ready(function(){     //do someting   });   $().ready(function(){ //do someting  }) 这三种方法都是JQuery的方法,写法不一样,但是效果一样.  2.这三个写法和$(window).load(function(){...}).onload()的区别 2.1.加载多个函数的

浅析jQuery(function(){})与(function(){})(jQuery)之间的区别

本篇文章主要是对jQuery(function(){})与(function(){})(jQuery)之间的区别进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助 Jquery是优秀的Javascrīpt框架.我们现在来讨论下在 Jquery 中两个页面载入后执行的函数. $(document).ready(function(){  // 在这里写你的代码...});在DOM加载完成时运行的代码 可以简写成 jQuery(function(){ }); (function($) {})(j

【转】jQuery中$(function(){})与(function($){})(jQuery)、$(document).ready(function(){})等的区别详细讲解

1.(function($) {…})(jQuery); 1).原理: 这实际上是匿名函数,如下: function(arg){…}这就定义了一个匿名函数,参数为arg 而调用函数时,是在函数后面写上括号和实参的,由于操作符的优先级,函数本身也需要用括号,即:(function(arg){…})(param)这就相当于定义了一个参数为arg的匿名函数,并且将param作为参数来调用这个匿名函数 而(function($){…})(jQuery)则是一样的,之所以只在形参使用$,是为了不与其他库冲