昨晚在对项目中的一部分做模块化处理的时候,遇到了一个问题,一个重新定义的function对一个通用类中的function进行赋值覆盖的时候,失败了。问题抽象出来是这样的:

<script >
var A=fun;
function fun(){
alert(1);
}
</script>
<script>
function fun(){
alert(2);
}
A();
</script>

我希望输出2,但是运行结果是1。如果两个代码块合并为一个,那输出结果就是2。

解释这个问题,涉及到两方面的内容:[JavaScript预编译和执行顺序]、[基本类型和引用类型]。

JavaScript预编译和执行顺序

  1.JavaScript的解析过程分为预编译和执行两个阶段,顺序都是从上到下。
  2.解析过程分块解析。如果页面有A、B两个<script>代码块,那么浏览器解释器的执行过程是:预编译A执行A → 预编译B执行B
  3.在预编译期会声明变量(仅声明未赋值)并定义函数。在执行阶段给变量赋值。
  4.变量没声明就引用,会报错。声明变量需使用var。
  参考http://blog.csdn.net/cxiaokai/article/details/7552653

根据以上三点,可以解释开头代码中"var A=fun;"为什么没有报错。因为预编译阶段声明了变量A并定义了函数fun,执行阶段变量fun赋值为函数A,所以不会报错。

但是,这样并不能解释为什么第二个代码块中的fun()没有把上一个代码块中的fun()覆盖掉。而如果代码最后运行fun()的话,输出的就是2。如此看来,代码运行到最后面的时候,A和fun已经不相等了。下面转换一下开头的例子:

<script >
var A=funA;
function funA(){}
</script>
<script>
function funA(){}
document.write(A===funA);
</script> <script >
var B=funB;
function funB(){}
function funB(){}
document.write(B===funB);
</script>

果然,上面代码块输出false,下面代码块输出true。这样看来应该是和变量A保存的是值还是地址有关系了。

基本类型和引用类型

  1.JavaScript的变量值可以是两种情况:基本类型值和引用类型值。
    基本数据类型:Undefined、Null、Boolean、Number、String;引用数据类型:Object。
  2.检测是否为引用数据类型可以使用 xx instanceof Object,如果是会返回true。

先使用xx instanceof Object对上面代码段A、funA进行引用类型检测,结果都为true。说明A和funA都是引用类型。再结合上面javascript预编译和执行顺序的研究,对上面示例代码可以这么解释了:

<script >
var A=funA;
function funA(){}
//函数为引用类型,即函数名表示一个指针
//预编译期声明A并定义funA,funA指向一个内存空间。执行期,通过对A赋值,A也指向了这个内存空间。
</script>
<script>
function funA(){}
document.write(A===funA);
//这里重新定义了funA,funA指向了新的内存空间,而A指向未变。所以A!==funA。
</script> <script >
var B=funB;
function funB(){}
function funB(){}
document.write(B===funB);
//预编译期声明B并定义funB,funB指向一个内存空间,接着重新定义了funB,funB指向新的内存空间。执行期,通过对B赋值,B也指向了这个新的内存空间。所以B===funB。
</script>

后记

朋友如果耐心看完了以上的内容,不妨猜一下下面这段代码的运行结果:

<script >
function a(){
alert(b);
alert(c);
}
a();
var b=1;
c=2;
</script>

关于JavaScript预编译和执行顺序以及函数引用类型的思考的更多相关文章

  1. javascript的预编译和执行顺序

    原文:javascript的预编译和执行顺序 最近在复习javascript的事件处理时发现了一个问题,然后也是我来写javascript的预编译和执行顺序的问题 代码: 代码一<html> ...

  2. JS的预编译和执行顺序 详析(及全局与局部变量)

    最近在复习javascript的事件处理时发现了一个问题,于是总结一下:javascript的预编译和执行顺序的问题:   <html> <head> <title> ...

  3. JS的预编译和执行顺序 详析

    原文:JS的预编译和执行顺序 详析 最近在复习javascript的事件处理时发现了一个问题,然后也是我来写javascript的预编译和执行顺序的问题   代码:   复制代码 代码一 <ht ...

  4. JS 的预编译和执行顺序

    脚本执行js引擎做的工作: 语法分析 预编译 解释执行

  5. JavaScript 预编译(变量提升和函数提升的原理)

    本文部分内容转自https://www.cnblogs.com/CBDoctor/p/3745246.html 1.变量提升 console.log(global); // undefined var ...

  6. javascript预编译和执行过程总结

    javascript相对于其它语言来说是一种弱类型的语言,在其它如java语言中,程序的执行需要有编译的阶段,而在javascript中也有类似的“预编译阶段”(javascript的预编译是以代码块 ...

  7. JS之预编译和执行顺序(全局和函数)

    预编译的两种情况 全局: 1.全局 直接是script标签中的代码,不包括函数执行 执行前: 1.首先生成一个GO(global object)对象,看不到,但是可以模拟出来用来分析 2.分析变量声明 ...

  8. JavaScript-深入理解JavaScript(一、预编译和执行过程)

    一.预解析 JavaScript 在执行前会进行类似“预解析”的操作:首先会创建一个在当前执行环境下的活动对象, 并将那些用 var 声明的变量.定义的函数设置为活动对象的属性, 但是此时这些变量的赋 ...

  9. javascript运行机制之执行顺序详解(转)

    转自http://www.admin10000.com/document/3385.html JavaScript是一种描述型脚本语言,它不同于java或C#等编译性语言,它不需要进行编译成中间语言, ...

随机推荐

  1. php 用 http post方法传输数据

    private function http_post($url,$post,$timeout){ $curl = curl_init(); curl_setopt($curl, CURLOPT_URL ...

  2. 工作总结_js

    工作至今已经有7个月了,虽然有进步,但是总感觉还是什么都不知道.可能这其中很大一部分还是与自己有关系,遇到自己不知道,问了人,或者百度到了,但是自己没有用心记.平时要用的时候,打开上一个项目,复制粘贴 ...

  3. final 140字评论

    按照演讲顺序 1.约跑app         个人感觉约跑现在做的已经很不错了,要是能添加地图就更好了. 2.礼物挑选         给人感觉在一定的时间做到这个程度,很不错很好,讲的声音有点小. ...

  4. SQL Server2000清除数据库日志

    sqlserver2000压缩日志 可以将jb51.ldf文件变得很小,方便备份数据库等,在sqlserver查询分析器中执行即可.复制代码 代码如下: DUMP TRANSACTION [jb51] ...

  5. 反向传播(BP)算法

    著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处.作者:刘皮皮链接:https://www.zhihu.com/question/24827633/answer/29120394来源 ...

  6. libreoffice转换文件为pdf文件乱码问题解决办法

    最近系统需要一个office文件预览功能 解决方案为使用libreoffice将office文件转换为pdf文件,然后使用swftools将pdf文件转换为swf文件 最后在前台使用flexpaper ...

  7. 分区里的inode号是0号和1号的block

    分区里的inode号是0号和1号的block 我相信大家在使用Linux的时候都遇到过误删文件系统数据的情况,不管是自己误删还是帮人家恢复误删 现在用的比较多的恢复工具大概是ext3grep .ext ...

  8. 微信双开是定时炸弹?关于非越狱iOS上微信分身高危插件ImgNaix的分析

    作者:蒸米@阿里移动安全 序言 微信作为手机上的第一大应用,有着上亿的用户.并且很多人都不只拥有一个微信帐号,有的微信账号是用于商业的,有的是用于私人的.可惜的是官方版的微信并不支持多开的功能,并且频 ...

  9. 玩转JavaScript OOP[2]——类的实现

    概述 当我们在谈论面向对象编程时,我们在谈论什么?我们首先谈论的是一些概念:对象.类.封装.继承.多态.对象和类是面向对象的基础,封装.继承和多态是面向对象编程的三大特性. JavaScript提供了 ...

  10. AutoMapper使用手册(一)

    阅读目录 1. 介绍 2. 基本使用 3. 自动分割映射(Flattening) 4. 自定义字段映射(Projection) 5. 验证配置(Configuration validation) 介绍 ...