标准参考

函数声明和函数表达式

定义一个函数有两种途径:函数声明和函数表达式。

函数声明:
function Identifier ( FormalParameterList

opt

 ) { FunctionBody }
函数表达式:
function Identifier

opt

 ( FormalParameterList

opt

 ) { FunctionBody }

ECMAScript 根据上下文来区分函数声明和函数表达式,假设 "function test(){}" 是一个表达式的一部分,它就是一个函数表达式,否则它就是一个函数声明。

关于函数声明和函数表达式的更多信息,请参考 ECMAScript 规范 13 Function Definition 中的内容。

函数声明可以出现的位置

根据 ECMAScript 规范第 13 章 Function Definition 和第 14 章 Program 中的描述,函数声明只能出现在 Program(程序,即全局环境)或函数体内。

换句话说,函数声明不能出现在( 如 if、while 或 for 语句)中。

问题描述

Firefox 的 TraceMonkey 引擎对函数声明的处理与 ECMAScript 规范的要求不符,TraceMonkey 将块中的函数声明作为“函数语句”来处理。而其他浏览器的引擎仍将这类块中的函数声明当作该块之外的函数声明来解析。

造成的影响

对块语句中的函数声明的处理差异,将导致某些功能不能按照预期实现,甚至代码出错。

受影响的浏览器

Firefox  

问题分析

TraceMonkey 将块中的函数声明作为“函数语句”来处理。而其他浏览器的引擎仍将这类块中的函数声明当作该块之外的函数声明来解析。

分析以下代码:

function foo(){
if(window===parent){
function bar(){alert(1);}
}
else{
function bar(){alert(2);}
}
bar();
}
foo();

以上代码中,两个标识符相同的函数声明被放在了 if...else... 块中。这不符合规范的约定,但各引擎的处理办法并不相同。

TraceMonkey 将这种位于块内的函数声明解析为“函数语句”,因此仅能被执行到的那个“函数语句”会生效,而其他浏览器则将二者仍看作当前作用域的函数声明,即不论 if...else... 的哪个分支最终会被执行,后者始终会覆盖前者,作为函数体 foo 内的、标识符为 foo 的函数存在。

注:Firefox 中在 if...else... 中使用函数声明的解析方式,在 MDC 中也有描述,参见:Conditionally defining a function

假设以上代码的判断条件 window===parent 为 true,各浏览器下的输出结果,如下表所示:

Firefox 其他浏览器
1 2

ECMAScript 规范第 5 版 12 章中的 Note 部分提到,虽然有些实现可以将函数声明作为语句处理,但这是不提倡的。

注:本文部分内容参考了文章:命名函数表达式探秘 中的内容。

解决方案

将条件语句中的函数声明替换为函数表达式,如:

function foo(){
if(window===parent){
var bar=function(){alert(1);}
}
else{
var bar=function(){alert(2);}
}
bar();
}
foo();

参见

知识库

相关问题

测试环境

操作系统版本: Windows 7 Ultimate build 7600
浏览器版本: IE6
IE7
IE8
Firefox 3.6
Chrome 4.0.302.3 dev
Safari 4.0.4
Opera 10.51
测试页面: ...
本文更新时间: 2010-07-09

关键字

函数声明 函数表达式 语句块 同名函数 Conditionally defining a function

转载

http://w3help.org/zh-cn/causes/SJ9002

Firefox 对条件判断语句块内的函数声明的处理与其他浏览器有差异的更多相关文章

  1. 前端笔记知识点整合之JavaScript(三)关于条件判断语句、循环语句那点事

      一.条件分支语句 条件分支语句,也叫作条件判断语句,就是根据某种条件执行某些语句,不执行某些语句. JS中有三种语法是可以表示条件分支的 1.1 if……else…… 条件分支的主力语法,这个主力 ...

  2. 前端笔记之JavaScript(三)关于条件判断语句、循环语句那点事

    一.条件分支语句 条件分支语句,也叫作条件判断语句,就是根据某种条件执行某些语句,不执行某些语句. JS中有三种语法是可以表示条件分支的 1.1 if……else…… 条件分支的主力语法,这个主力语法 ...

  3. puppet(3) 变量、数据类型、表达式、条件判断语句-if、case、selector、unless

    puppet(4) 变量.数据类型.表达式.条件判断语句-if.case.selector语句 puppet变量: 1.名称必须以$开头:赋值使用=,支持追加赋值+=: 2.每个变量都有两种引用格式: ...

  4. python学习_条件判断语句_if

    #条件判断语句(if)#语法:if条件表达式:语句# 代码块#执行流程:if语句在执行时,会先对条件表达式进行求值判断#如果为True,则执行if后面的语句#如果为False,则不执行#默认情况下,i ...

  5. [19/09/16-星期一] Python的运算符和条件判断语句

    一.运算符 (1)算术运算符  + 加法运算符(如果是两个字符串之间进行加法运算,则会进行拼串操作) a = 10 + 5  计算 a = 'hello' + ' ' + 'world' 拼串  - ...

  6. Interview----求 1+2+...+n, 不能用乘除法、for、while if、else、switch、case 等关键字以及条件判断语句 (A?B:C)

    题目描述: 求 1+2+...+n, 要求不能使用乘除法.for.while.if.else.switch.case 等关键字以及条件判断语句 (A?B:C). 分析: 首先想到的是写递归函数,但是遇 ...

  7. 求1+2+…+n,要求不能使用乘除法、for、while、if、else、s witch、case 等关键字以及条件判断语句(A?B:C)和不用循环/goto/递归输出1~100的10种写法

    来源:据说是某一年某个公司的面试题 题目:求1+2+…+n, 要求不能使用乘除法.for.while.if.else.s witch.case 等关键字以及条件判断语句(A?B:C) 分析:这题本来很 ...

  8. if条件判断语句的不同

    let number = ["a":1, "b":2, "c":3]; if let num = number["d"] ...

  9. shell编程基础(3)条件判断语句

    1,带参数的shellscript #this is program build 5.11 to test shell script ############ cxz ####### 5.11 ### ...

随机推荐

  1. 【Tech】Cassandra安装和启动

    1.安装 jre,配置系统环境变量: 2.安装python,配置环境变量: 3.下载cassandra,http://cassandra.apache.org/download/: 4.解压,这里我没 ...

  2. 《JAVA编程那点事儿》读书笔记(二)——类和对象

    方法: 1. 基本的main方法: public static void main(String[] args) 2.静态方法内部调用非静态方法:重新声明一个类,通过这个类来调用非静态方法 publi ...

  3. dojo 十一 jsonp

    官方教程:Getting Jiggy with JSONPDojo对Ajax实现的框架XHR的功能很强大,但 XHR 框架的函数有一问题就是不能跨域访问,浏览器不允许 XHR 对象访问其他域的站点.此 ...

  4. java web每天定时执行任务

    第一步: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 ...

  5. Android HTTPS(4)直接用SSLSocket,黑名单,客户端证书

    Warnings About Using SSLSocket Directly So far, the examples have focused on HTTPS using HttpsURLCon ...

  6. MTK6577 Android源代码目录

    MTK6577 Android源代码目录 1.     MTKAndroid4.0 源代码目录 (1)  makeMtk 整个工程编译或是构建(make/build)的入口. (2)  abi 应用程 ...

  7. Android实现图片裁切

    介绍 在应用开发中,如果涉及到个人信息,头像一般是不可避免的,类似这种情况,我们就需要用到图片裁切的功能,实现头像裁切,然后上传给服务器. 一般裁切的做法就是图层叠加选取框,然后根据坐标,计算裁切区域 ...

  8. KEYUSE

    typedef struct keyuse_t { TABLE *table; Item *val; /**< or value if no field */ table_map used_ta ...

  9. gdb mysq

    1.找到mysqld的id [root@default-tpl ~]# ps aux|grep mysqldroot 5006 0.0 0.0 103252 796 pts/6 S+ 15:15 0: ...

  10. Qt之设置QWidget背景色

    简述 QWidget是所有用户界面对象的基类,这意味着可以用同样的方法为其它子类控件改变背景颜色. Qt中窗口背景的设置,下面介绍三种方法. 使用QPalette 使用Style Sheet 绘图事件 ...