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. Redis(2015.08.03笔记一)

    一.redis简介 Redis是一种面向"键/值"对数据类型的内存数据库,可以满足我们对海量数据的读写需求. redis的键只能是字符串 redis的值支持多种数据类型: 1:字符 ...

  2. CDMA sid, nid, bid 含义解释

    copyright@ celldb.cc SID 是系统识别码,每个地级市只有一个sid,是唯一的. NID是网络识别码,由各本地网管理,也就是由地级分公司分配.每个地级市可能有1到3个nid. BI ...

  3. cephfs创建及挂载

    Ceph 文件系统( Ceph FS )是个 POSIX 兼容的文件系统,它使用 Ceph 存储集群来存储数据.Ceph 文件系统要求 Ceph 存储集群内至少有一个 Ceph 元数据服务器. 1.添 ...

  4. 【C++】浅谈三大特性之一继承(三)

    四,派生类的六个默认成员函数 在继承关系里,如果我们没有显示的定义这六个成员函数,则编译系统会在适合场合为我们自动合成. 继承关系中构造函数和析构函数的调用顺序: class B { public: ...

  5. String 类的实现(1)浅拷贝存在的问题

    浅拷贝 : 也称位拷贝 , 编译器只是直接将指针的值拷贝过来, 结果多个对象共用 同 一块内 存, 当一个对象将这块内 存释放掉之后, 另 一些对象不知道该块空间 已经还给了 系 统, 以 为还有效, ...

  6. Python之路-计算机基础

    一·计算机的组成 一套完整的计算机系统分为:计算机硬件,操作系统,软件.   硬件系统:运算器,控制器和存储器 ,输入设备,输出设备. 1.运算器:负责算数运算和逻辑运算,与控制器一起组成CPU. 2 ...

  7. yii2-验证规则,rules,判断条件

    yii2模型的验证规则,简单的使用我就不详细说了,想看的可以去看官网教程http://www.yiichina.com/doc/guide/2.0/structure-models#validatio ...

  8. Flex——弹性布局

    今天在做项目时,要一个500*100的页面区域做三个橱窗,尼玛可是恶心死我了!光是计算左右内外边距,左右宽度,就废了一上午时间~~好吧,我承认我的数学老师挂得早! 正在苦逼的列公式,定位图片,浮动文字 ...

  9. 1029. Median

    Given an increasing sequence S of N integers, the median is the number at the middle position. For e ...

  10. 最近公共祖先LCA(Tarjan算法)的思考和算法实现

    LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现 小广告:METO CODE 安溪一中信息学在线评测系统(OJ) //由于这是第一篇博客..有点瑕疵...比如我把false写成了f ...