打印

SJ9001: IE6 IE7 IE8 的函数声明和函数表达式的实现与其他浏览器有差异

作者:蔡美纯 孙东国

标准参考

函数声明和函数表达式

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

函数声明:
function Identifier ( FormalParameterListopt ) { FunctionBody }
函数表达式:
function Identifieropt ( FormalParameterListopt ) { FunctionBody }

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

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

标识符

在 ECMAScript 中,变量名、对象的属性或方法名都是标识符,标识符可以包含英文字母、数字、美元符号 '$' 和下划线 '_',但不能以数字开头,不能是保留字。

换句话说,'+','.' 等符号是不能出现在标识符中的。

关于标识符的更多信息,请参考 ECMAScript 规范 7.6 Identifier Names and Identifiers 的内容。

问题描述

IE 的函数声明和函数表达式的实现与 ECMA 规范都有出入。

在 IE 中:
函数声明中的标识符允许是一个包含 '.' 运算符的表达式。(在绑定事件时,可以将事件名前的 '.' 替换为 '::'。 )
函数表达式中的标识符则可以在该函数外部被访问。

造成的影响

依赖 IE 的上述“特性”编写的代码,在其他浏览器中将不能按照预期的方式执行。

例如以 'function window.onload() {}' 形式定义的事件处理函数仅在 IE 中有效,在其他浏览器中将报语法错误。

受影响的浏览器

IE6 IE7 IE8

问题分析

1. 函数声明中的标识符允许是一个包含 '.' 运算符的表达式。(在绑定事件时,可以将事件名前的 '.' 替换为 '::'。 )

分析以下代码:

function A(){}
function A.prototype.b(){}
var a=new A();
alert(typeof a.b);

本例中,第二个函数声明的标识符是非法标识符,它包含了 '.' 运算符。

各浏览器表现如下:

IE6 IE7 IE8 其他浏览器
function 浏览器报错(语法错误)

可见:以上写法只有 IE 支持。

2. 函数表达式中的标识符则可以在该函数外部被访问。

分析以下代码:

var a=function b(){};
alert(typeof b);

根据 ECMA 规范中的规定,以上函数表达式中的标识符 b 将仅在该函数的内部可以被访问,即 b 仅在该函数的作用域内有效,外部无法访问。

各浏览器表现如下:

IE6 IE7 IE8 其他浏览器
function undefined

可见:IE 没有遵循规范,函数表达式中的标识符在该函数外围的作用域内也可以访问。

注:本文部分内容参考了文章:Named function expressions demystified(中文翻译:命名函数表达式探秘)中的内容。

解决方案

避免使用 IE 的这些“特性”,以保证兼容所有浏览器。

参见

知识库

相关问题

测试环境

操作系统版本: 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-02

关键字

Named Function Declaration Expression 函数 声明 表达式