JavaScript是一门有趣的语言,不仅有趣而且调皮,不同的内核的浏览器在解析的时候表现会有些差异,今天主要是抛砖引玉,和大家一起讨论一些在实际开发中比较常见但同时可能并没有过于在意的JavaScript表现。这里先做几个约定: 由于JavaScript是一门解释性语言,自然没有编译过程,但在脚本执行之前会有语法检查和执行环境的构建,我们把这一过程姑且称为预处理吧。
当使用var关键字来声明一个变量或者函数时,我们把这一过程称为变量声明和函数声明,当使用表达式形如function fn() = {}来定义一个函数的方式称为函数定义。
文中实例的测试环境是我电脑上安装的IE9、FF4.0、chrome 14.0三个不同内核的浏览器。
好吧,接下来进入正题,主要看一些简单的demo来观察和了解浏览器是怎样初始化JavaScript中的变量以及函数,主要涉及到的点包括JavaScript中的作用域以及执行环境,对这方便不是很了解的朋友可以参考文章最后的相关链接,看一些简单的demo吧。
DEMO1、函数声明
 
 
这个能说明什么呢?第一次调用fn时访问的是通过函数定义的方法,第二次调用访问的是通过函数定义的方法,那么这整个过程从预处理到执行完毕是谁覆盖了谁,谁的优先级更高呢?带着这个疑惑接着测试。
DEMO2、 关于局部变量和全局变量的访问
 
 
 
这里在fn方法中依次输出了四个变量,不知道结果和你预期的有没有差异,输出的第一个参数num1在局部和全局环境中都有声明,局部变量优先级高于全局变量无可厚非,这里不一样的是在声明变量之前访问了num1,说明在预处理阶段构造执行环境时已经为局部变量分配了存储空间,赋的初始值是undefined罢了,输出的第二个变量num3在arguments和局部变量中都有,输出的是arguments中的参数变量,如果前面一个结论成立,那么说明arguments中的变量覆盖了局部环境中的变量,也就是说通过变量定义的方式优先级高于arguments对象数组中定义的变量。第三个输出num4时会报错误,说明连续赋值操作中除第一个变量以外的变量被视为全局变量处理,而全局环境中没有相关定义所以会出错,第四个num2输出出错也是由于被视为全局变量的原因,这两个地方的错误应该可以引用这样一句话:“个人自扫门前雪,莫管他人瓦上霜”,也就是说预处理阶段一个独立的执行环境只会维护自己内部的变量,忽略其他环境的变量。
DEMO3、函数的调用
 
 
 
这个demo主要目的是比较arguments、函数定义和函数声明三种方式的一个优先级,从结果知道输出的是通过函数声明的方式定义的函数,从上一个实例得出的结论是arguments中变量会覆盖var方式定义的变量,这里arguments中的变量又被函数定义的方法覆盖了,那我们可以得到这样一个结论:将函数声明为变量(var t = function(){})的方式优先级最高,在预处理阶段被初始化,执行时会先被arguments中的变量覆盖,最后被通过函数定义(function t(){})创建的变量覆盖,这一过程完毕后程序才开始执行。
众所周知JavaScript中没有块级作用域,浏览器间也是表现一致的,比如以下代码:
 
 
 
好吧,在这一点上没有任何疑问,那接下来继续看下面一段代码:
DEMO4
 
 
 
这段代码的输出是什么呢,我觉得不防自己测试下,在IE中和chrome中会输出”function fn(){return 2;}”,在FF中是会报错的,那如果代码改成:
 
 
 
输出的结果在IE和chrome中没有变化,在FF中变成了”function fn(){return 1;}”,这个结果可能和你之前预想的不太一样,我在网上看了一些网站对此也有不同的说法,有些说是FF的bug,个人觉得不应该算bug,毕竟每一个浏览器厂商在实现ECMAScript的标准时会有差异,不能因为和大多数人实现的不一样,就把自己视为错误吧。那为什么会出现这种差异呢,个人觉得是在预处理阶段构建执行环境时对块状作用域的处理上有一些差异,首先先确认一点,如果在块级作用域中通过var关键字声明一个变量,那么不管在声明语句之前还是之后访问该变量都是没有问题的,因为在构建执行环境时会找出所有本域中通过var定义的变量并分配空间,但是通过函数定义的方式就不一样了,IE和chrome会在构建的时候初始化函数对象,并且后面的定义会覆盖前面的定义,从上面的代码还可以看出一点,由于在预处理阶段已经处理了函数定义,在代码的执行阶段不管代码逻辑如何都会直接忽略函数的定义(这点很重要),而在FF中预处理时会忽略块级作用域中的函数定义,在代码执行时再进行初始化,两种实现方式从性能和效率上来说个人感觉FF的实现方式更合理一些,所以不能把这种实现方式归类于bug,当然纯属个人观点。
DEMO5、关于命名函数表达式
 
 
 
先看一下结果,在IE8及以下版本中输出的true,IE9、FF以及chrome中输出的是false。好吧,先讨论下命名函数表达式,格式如下:
 
 
 
在声明一个函数的同时为其指定一个别名,这个别名在IE8及以下版本中在外部是可以访问的,在IE9、FF或者chrome中只能在函数内部访问,这就是为什么会出现DEMO5中那样的情况了,在外部可以访问会造成诸多问题,比如变量名污染等,所以建议在实际开发中不采用这种写法。
好了,瞎扯了这么多,大牛就一笑而过吧。最后还是简单的总结下,在做前端开发的时候,了解浏览器解析JavaScript的过程对写出规范的代码是很有必要的,这样可以减少一些不必要的错误,以后再继续探讨这些有趣的问题。
 
 
本文转载自分针网

分针网—IT教育:调皮的JavaScript的更多相关文章

  1. 分针网—IT教育: jquery选择器的用法

    jQuery选择器是jQuery库的一大特色,用这些选择器不但可以省去繁琐的JavaScript 书写方式,还可以节省时间和效率,正是有这些jQuery选择器,才让我们更容易的操作JavaScript ...

  2. 分针网—IT教育: Html / CSS常见问题的解决方案

    1. 解决Safari下input光标过大   2. 设置浮层   3. CSS绘制三角形   4. 清除浮动   1) 浮动元素父级添加样式   2) 父元素后添加伪元素     3) 同样可以使用 ...

  3. 分针网—IT教育:作为PHP开发人员容易忽视的几个重点

    无论是学习什么样的一个开发.ASP开发.java开发.当学习还不是很久的时候,一般都是不知道它们的精华是在哪里,而现在很多的php程序员也是不知道PHP的精华所在,为什么perl在当年在商界如此的出名 ...

  4. 分针网—IT教育:使用CSS3制作导航条和毛玻璃效果

    导航条对于每一个Web前端攻城狮来说并不陌生,但是毛玻璃可能会相对陌生一些.简单的说,毛玻璃其实就是让图片或者背景使用相应的方法进行模糊处理.这种效果对用户来说是十分具有视觉冲击力的.本次分享的主题: ...

  5. 分针网—每日分享: 怎么轻松学习JavaScript

    js给初学者的印象总是那么的"杂而乱",相信很多初学者都在找轻松学习js的途径.   我试着总结自己学习多年js的经验,希望能给后来的学习者探索出一条"轻松学习js之路& ...

  6. 分针网—每日分享:HTML解析原理

    标准的web前端工程师需要知道 ◎浏览器(或者相应播放器)的渲染/重绘原理   这我得加把劲了.我还真的说的不是很清楚,我就G下,结果不是很多,找到了有一个,就记下来了...   以下部分来自hand ...

  7. 分针网——每日分享: jquery选择器的用法

    jQuery选择器是jQuery库的一大特色,用这些选择器不但可以省去繁琐的JavaScript 书写方式,还可以节省时间和效率,正是有这些jQuery选择器,才让我们更容易的操作JavaScript ...

  8. 【模拟,时针分针秒针两两夹角】【没有跳坑好兴奋】hdu - 5387 (多校#8 1008)

    算是最好写的一道题了吧,最近模拟没手感,一次过也是很鸡冻o(* ̄▽ ̄*)o 注意事项都在代码里,没有跳坑也不清楚坑点在哪~ #include<cstdio> #include<cst ...

  9. Android_模拟时钟内时针、分针触摸转动

    最近实现了android里的一个机能,在activity里面画了一个模拟的时针,然后触摸上面的时针跟分针可以实现调时间的功能. 其实,说起原来来还是挺简单的,但是我花了将近一周的时间才全部实现,有点惭 ...

随机推荐

  1. oracle监听(lsnrctl)详解解读

    (总结)Oracle监听服务lsnrctl参数及查询状态详解   lsnrctl命令常用参数详解: lsnrctlstart启动指定的监听器 stop关闭指定的监听器 status显示监听器的状态.s ...

  2. vpn的实现原理

    由于公共IP的短缺,我们在组建局域网时,通常使用保留地址作为内部IP,(比如最常用的C类保留地址:192.168.0.0-192.168.255.255)这些地址是不会被互联网分配的,因此它们在互联网 ...

  3. 运行错误:应用程序无法启动因为并行配置不正确。the application has failed to start because its side-by-side configuration is incorrect 解决方法

    问题描述: 当电脑同时安装VS2008和VS2008 SP1时,编译出来的Visual C++程序的manifest 文件会默认引用VS2008的MFC版本和CRT版本.如下: <depende ...

  4. Struts2之Action与配置文件

    一.Struts2配置文件 1.struts.properties 在学习Action之前先学下Struts2的配置文件,与Struts2相关的配置文件有好几个,常用的有Struts.xml,web. ...

  5. Kruskal算法的实现

    #include "stdio.h" #include "stdlib.h" struct edge { int m; int n; int d; }a[]; ...

  6. javaWEB与EL表达式

    EL表达式1. EL是JSP内置的表达式语言!  * jsp2.0开始,不让再使用java脚本,而是使用el表达式和动态标签来替代java脚本!  * EL替代的是<%= ... %>,也 ...

  7. 深入hibernate的三种状态

    学过hibernate的人都可能都知道hibernate有三种状态,transient(瞬时状态),persistent(持久化状态)以及detached(离线状态),大家伙也许也知道这三者之间的区别 ...

  8. JavaWeb之cookie

    什么叫做会话 ? 用户从打开一个浏览器开始,浏览器网站,到关闭浏览器的整个过程叫做一次会话! 每个用户与服务器进行交互的过程中,各自会有一些数据,程序要想办法保存每个用户的数据. 例如:用户点击超链接 ...

  9. Excel图表-"DNA"图

    p{ font-size: 15px; } .alexrootdiv>div{ background: #eeeeee; border: 1px solid #aaa; width: 99%; ...

  10. Linux简介与厂商版本上

    Linux简介与厂商版本   作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 1. Linux简介 Linux可以有狭义和广义两种 ...