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. SQLServer 数据库不能重命名的解决方案

    无法用排他锁锁定该数据库,以执行该操作 SQL Server2008 因为可能其他用户在占用着该数据库 解决办法为 把数据库先改为单用户的,再改数据库名,再改回多用户的 USE [master] GO ...

  2. Spring Boot 注解的使用

    Spring Boot 优于Spring mvc ,SSM,SSH 的一个亮点就是他使用了好多的注解. 1. @Autowired 这个注解的作用是将其他的类,接口引入,类似于之前的类的初始化等,用这 ...

  3. 学习了php之后再来看php怎样学java

    我用了一天时间学会了php,真的.我现在已经可以流畅的用thinkphp框架开发php了.学习过程是这样的:我接了个php的项目,包括两个部分:老系统添加功能和优化,再新做一个系统.已经答应给人家做了 ...

  4. IOS-验证码的实现和封装(可以直接调用)

    最近对OC中的图像比较感兴趣.随手搞得一个类似验证码的demo.直接贴代码了. 小demo中的VerificationCodeView是继承自UIView的,所以需要用到的时候,可以直接定义一个UIV ...

  5. 使用VB6写一个自定义的进度信息框窗口

    一.起因说明 之前有些项目是用Access完成的,当时为了给用户显示一些进度信息,自制了一个进度信息窗体,类似下图所示: 随着项目不断变迁,需要将进度信息按阶段及子进度进行显示,并且出于代码封装的需求 ...

  6. 安全性测试之防范 DDoS 攻击

    安全性测试之防范 DDoS 攻击   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:90882 ...

  7. 老李分享:为何要使用 Web Services

    老李分享:为何要使用 Web Services   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询q ...

  8. [转]使用sklearn进行集成学习——理论

    转:http://www.cnblogs.com/jasonfreak/p/5657196.html 目录 1 前言2 集成学习是什么?3 偏差和方差 3.1 模型的偏差和方差是什么? 3.2 bag ...

  9. jQ层级选择器

    <!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title> ...

  10. 使用express创建新应用的骨架

    通过应用生成器工具 express 可以快速创建一个应用的骨架. 通过如下命令安装: $ npm install express-generator -g -h 选项可以列出所有可用的命令行选项: $ ...