在下面描述中,IE表示Internet Explorer,FF表示Mozilla Firefox浏览器。
1.空白符
IE不支持v字符为空白符,会把它解析为字母v。
示例:
alert(/'v supported/'+(String.fromCharCode(11)==/'v/'));
输出:
IE:false FF:true
Opera:true Safari:true
2.保留字
ECMA Script v3定义了25个关键字:break、else、new、var、case、finally、return、void、catch、for、switch、while、continue、function、this、with、default、if、throw、delete、in、try、do、instanceof、typeof。
同时还预留了31个保留字用于未来版本的功能扩展:abstract、enum、int、short、boolean、export、interface、static、byte、extends、long、super、char、final、native、synchronized、class、float、package、throws、const、goto、private、transient、debugger、implements、protected、volatile、double、import、public。
所有保留字可以作为标识符在代码中使用,而IE仅允许下面23个保留字作为标识符使用:abstract、int、short、boolean、interface、static、byte、long、char、final、native、synchronized、float、package、throws、goto、private、transient、implements、protected、volatile、double、public。
3.字面量
IE借用C语言风格的转义字符,设置文字的换行符,但根据ECMAScript v3标准,这种行为将引发一个未结束的字符串常量的语法错误。
示例:
var s=/"this is a
multiline string/";
输出:
IE、FF、Opera、Safari:/"this is a multiline string/"
IE会把上面字符串视为单行字符串,FF、Opera、Safari与IE解析一致。
IE会忽略“”及其后面的字符。s.length将返回34(这包括在第二行中的前导空格)。
4.Arguments对象
不同引擎没有针对函数的arguments变量名实现统一的处理方式。在IE中,arguments并没有包含在变量所在的上下文环境中,调用eval动态执行代码将无法改变arguments的值。
示例:
function foo{
document.write(arguments);
document.write(arguments[0]);
eval(/"arguments=10;/");
document.write(arguments);
document.write(arguments[0]);
}
foo(/"test/");
输出:
IE:[object Object]test[object Object]test
FF:[object Object]test10undefined
Opera:testtest10undefined
Safari:[object Arguments]test10undefined
针对上面示例,如果不使用eval动态执行字符串,而是直接修改arguments变量的值:
function foo{
document.write(arguments);
document.write(arguments[0]);
arguments=10;
document.write(arguments);
document.write(arguments[0]);
}
foo(42);
则不同引擎的输出结果如下:
IE:[object Object]4210undefined
FF:[object Object]4210undefined
Opera:424210undefined
Safari:[object Arguments]4210undefined
5.Global对象
在IE中,全局对象(Global)不能使用this进行迭代。
示例:
var__global__=this;
function invisibleToIE{
document.write(/"IE can/'t see me/");
}
__global__.visibleToIE=function{
document.write(/"IE sees me/");
}
for(func in__global__){
var f=__global__[func];
if(func.match(/visible/)){
f;
}
}
输出:
IE:IE sees me
FF:IE sees meIE can/'t see me
Opera:IE can/'t see meIE sees me
Safari:IE can/'t see meIE sees me
在IE中,在使用delete运算符通过this指针删除全局成员时,将会产生运行时错误,而在FF等浏览器中删除返回false。根据标准,FF的行为是正确的,例如:
var__global__=this;
function invisibleToIE{
document.write(/"IE can’t see me/");
}
__global__.visibleToIE=function{
document.write(/"IE sees me/");
}
document.write(delete this.invisibleToIE);
输出:
IE:runtime error(object doesn’t support this action)
FF、Opera、Safari:false
在IE中全局对象(Global)不继承Object.prototype,即使它的类型是对象。根据JavaScript原型继承规则,全局对象应该继承Object.prototype,当然这些都必须依赖于实现的浏览器。作为内置的原型,必须遵循Object.prototype的标准方法。
var__global__=this;
document.write(typeof(__global__)+/'<br>/');
var f=[/'toString/',/'toLocaleString/',/'valueOf/',/'hasOwnProperty/',/'isPrototypeOf/',/'propertyIsEnumerable/'];
for(i=0;i<f.length;i++){
test(f[i]);
}
function test(s){
if(__global__[s]){
document.write(s+/'supported/'+/'<br>/');
}
}
输出:
IE:
object
toString supported
FF、Opera、Safari:
object
toString supported
toLocaleString supported
valueOf supported
hasOwnProperty supported
isPrototypeOf supported
propertyIsEnumerable supported
6.初始化数组
在IE中,向数组尾部添加逗号分隔符将会增加数组的长度。IE把尾部逗号后的空白视为一个值为undefined的元素。实际上,这是一个非法解析的错误。
示例:
document.write([1,2,3,].length);
输出:
IE:4
FF、Opera、Safari:3
7.函数表达式
在IE中,函数表达式中的标识符在闭包的上下文环境中是可见的,因为这种表达被视为函数声明。
示例:
var foo=function bar(b){
if(b==true){
bar;//可以工作,因为在函数内部bar标识符是可见的
}else{
document.write(/"hello/");
}
}
foo;//可以工作,因为foo标识符指向一个函数对象
bar(false);//失败,因为在全局环境中bar是不可见的
输出:
IE:/"hellohello/"
FF:/"hello/"接着显示一个语法错误(bar is not defined)
Opera:/"hello/"接着显示一个引用错误(Reference to undefined variable:bar)
Safari:/"hello/"
IE把嵌套在函数表达式中的一个函数名称作为一个函数声明,这个函数声明位于封闭的上下文环境中。在下面的示例中,IE可以向前引用x,而在其他浏览器中将显示语法错误。
function f(x){
x;
y=function x{
document.write(/"inner called/")
};
document.write(x);
document.write(arguments[0]);
}
document.write(/"test 4/");
f(/"param/");
输出:
IE:test 4 inner called function x{document.write(/"inner called/")}function x{document.write(/"inner called/")}
FF、Opera、Safari:test 4
再如:
function foo{
function bar{}
var x=function baz(z){
document.write(/"baz/"+z);
if(z)baz(false);
};
x(true);//合法的
bar;//合法的
baz(true);//原来是非法的,现在是合法的
}
foo;
输出:
IE:baztruebazfalsebaztruebazfalse FF:baztruebazfalse(followed by an error-baz not defined)Opera:same as FF
FF、Opera、Safari:baztruebazfalse(followed by an error-baz not defined)
8.抽象关系比较算法
IE使用or而不是and进行字符串比较计算。
示例:
document.write(/'1<10==/'+(1<10)+/'<br>/');
document.write(/'NaN<1==/'+(NaN<1)+/'<br>/');
document.write(/'1<Infinity==/'+(1<Infinity)+/'<br>/');
document.write(/'/"10/"<1==/'+(/"10/"<1)+/'<br>/');
document.write(/'1</"a/"==/'+(1</"a/")+/'<br>/');
document.write(/'/"a/"</"b/"==/'+(/"a/"</"b/")+/'<br>/');
输出:
IE、FF、Opera、Safari:
1<10==true
NaN<1==false
1<Infinity==true
/"10/"<1==false
1</"a/"==false
/"a/"</"b/"==true
9.函数体内的函数声明
当使用函数声明定义一个函数时,不管怎样使用with语句修改函数的作用域,IE都会把它绑定到全局作用域上。
示例:
var v=/'value 1/';
var o={v:/'value 2/'};
function f1{
alert(/'v==/'+v);
};
with(o){
function f2{
alert(/'v==/'+v);
};
}
f1;
f2;
//修改变量的值
v=/'modified value 1/';
o.v=/'modified value 2/';
f1;
f2;
输出:
IE、Opera:
v==value 1
v==value 1
v==modified value 1
v==modified value 1
FF、Safari:
v==value 1
v==value 2
v==modified value 1
v==modified value 2
针对上面示例,如果使用函数表达式定义f1和f2函数(代码如下),那么输出结果与FF相同,说明在IE、Opera浏览器中with作用域会影响函数表达式,但不会影响函数声明。
var f1=function{
alert(/'v==/'+v);
};
with(o){
var f2=function{
alert(/'v==/'+v);
};
}
10.枚举和属性
IE不支持通过for in语句枚举类型的自定义属性,这些自定义属性通过Object.prototype进行映射进而实现继承。
示例:
function cowboy{
this.toString=function{
return/"cowboy/";
}
this.shoot=function{
return/"bang!/";
}
}
var p=new cowboy;
document.write(/"Enumerable properties:/");
for(var i in p){
document.write(/"/",i);
}
document.write(/"<br/>cowboy propertyIsEnumerable(/"toString/"):/",p.propertyIsEn-umerable(/"toString/"));
document.write(/"<br/>cowboy hasOwnProperty(/"toString/"):/",p.hasOwnProperty(/"toString/"));
输出:
IE:
Enumerable properties:shoot
cowboy propertyIsEnumerable(/"toString/"):false
cowboy hasOwnProperty(/"toString/"):true
FF、Opera、Safari:
Enumerable properties:toString shoot
cowboy propertyIsEnumerable(/"toString/"):true
cowboy hasOwnProperty(/"toString/"):true
11.try语句
在IE中,用于保存捕获异常的变量在当前上下文环境是可见的,在catch子句执行完毕后此变量依然存在,但在该上下文环境被注销后会随之消失。
示例:
function foo{
try{
throw/"hello/";
}catch(x){
document.write(x);
}
document.write(x);//x在这里应该是不可见的
}
foo;
输出:
IE:hellohello
FF、Opera、Safari:
hello(然后抛出一个错误,x is not defined)
try语句包含自己的作用域,当抛出异常时,这个作用域是封闭的,但在IE和FF浏览器中可以看到一些特殊的情况。示例如下:
function foo{
this.x=11;
}
x=/"global.x/";
try{
throw foo;
}catch(e){
document.write(x)//应该输出/"global.x/"
e;
document.write(x)//应该把x添加到e对象上,但IE和FF却修改了全局变量x
}
document.write(x);//应该输出/"global.x/"
输出:
IE、FF:global.x1111
Opera、Safari:global.x11global.x
12.jion数组原型
当分隔符为undefined时,IE会使用“undefined”字符串作为分隔符来连接数组成员值。
示例:
var array=[1,2];
alert(array.join);
alert(array.join(undefined));
alert(array.join(/'-/'));
输出:
IE:
1,2
1undefined2
1-2
FF、Opera、Safari:
1,2
1,2
1-2
13.unshift数组原型
Array.unshift方法能够把它的参数添加到数组的起始位置,同时返回结果数组的长度,但IE在调用Array.unshift方法时的返回值为undefined。
示例:
var a=new Array(1,2,3);
var l=a.unshift;
document.write(l,/"/");
document.write(a.length,/"/");
document.write(a,/"/");
l=a.unshift(2);
document.write(l,/"/");
document.write(a.length,/"/");
document.write(a,/"/");
输出:
IE:undefined 3 1,2,3 undefined 4 2,1,2,3
FF、Opera、Safari:
3 3 1,2,3 4 4 2,1,2,3
14.函数length属性
Object.length、String.fromCharCode.length、String.Prototype.indexOf.length、String.Prototype.lastIndexOf.length、String.prototype.slice.length等的返回值与标准值存在差异。
❑Object.length:IE返回值为0,标准解析为1。
❑String.fromCharCode.length:IE返回值为0,标准解析为1。
❑String.prototype.indexOf.length:IE返回值为2,标准解析为1。
❑String.prototype.lastIndexOf.length:IE返回值为2,标准解析为1。
❑String.prototype.slice.length:IE和FF返回值为0,标准解析为2。
15.split字符串原型
IE可以忽略捕获括号,FF能够使用空字符代替undefined。
示例:
alert(/"A<B>bold</B>and<CODE>coded</CODE>/".split(/<(/)?([^<>]+)>/));
输出:
IE:A,bold,and,coded
FF、Opera、Safari:
A,,B,bold,/,B,and,,CODE,coded,/,CODE,
16.toPrecision数值原型
如果参数的精度不确定,则IE将抛出RangeError异常。
示例:
var number=123.456;
document.write(/'number.toString==/'+number.toString+/'<br>/');
document.write(/'number==/'+number+/'<br>/');
try{
document.write(/'number.toPrecision(undefined)==/'+number.toPrecision(undefined)+/'<br>/');
}catch(e){
document.write(/'Exception thrown./'+e.name+/':/'+e.message+/'<br>/');
}
输出:
IE:
number.toString==123.456
number==123.456
Exception thrown.RangeError:The precision is out of range
FF、Opera、Safari:
number.toString==123.456
number==123.456
number.toPrecision(undefined)==123.456
17.valueOf日期原型
直接调用日期原型的valueOf方法,IE将返回0,而标准规定为NaN。
示例:
document.write(/'Date.prototype.valueOf==/'+Date.prototype.valueOf);
输出:
IE:0
FF、Opera、Safari:NaN
18.Disjunction
IE将使用空字符代替undefined值。
示例:
//重写Array.prototype.toString,使字符串包含在引号中,同时显示undefined值
Array.prototype.toString=function{
var s=/'/';
for(var i=0;i<this.length;i++){
if(s){
s+=/',/';
}
switch(typeof this[i]){
case/'string/':
s+=/"/'/"+this[i]+/"/'/";
break;
case/'undefined/':
s+=/'undefined/';
break;
default:
s+=this[i];
break;
}
}
return/'[/'+s+/']/';
}
var a=/((a)|(ab))((c)|(bc))/.exec(/'abc/');
document.write(a);
输出:
IE:[/'abc/',/'a/',/'a/',/'/',/'bc/',/'/',/'bc/']
FF、Opera、Safari:NaN
[/'abc/',/'a/',/'a/',undefined,/'bc/',undefined,/'bc/']
19.数列
IE不清除子表达式中重复匹配的选项。
示例:
Array.prototype.toString=function{
//执行代码
}
var a1=/(z)((a+)?(b+)?(c))*/.exec(/'zaacbbbcac/');
var a2=/(a*)*/.exec(/'b/');
document.write(a1);
document.write(/'<br>/');
document.write(a2);
输出:
IE:
[/'zaacbbbcac/',/'z/',/'ac/',/'a/',/'bbb/',/'c/']
[/'/',/'/']
FF、Opera、Safari:
[/'zaacbbbcac/',/'z/',/'ac/',/'a/',undefined,/'c/']
[/'/',undefined]
20.正则表达式实现
如果正则表达式的标志中包含任何字符,那么超出了“g”、“i”、“m”,或者这几个字符重复都将抛出SyntaxError异常。但IE不会抛出SyntaxError或TypeError异常,它会抛出一个TypeError异常,由此可知,IE对正则表达式字符串的要求是宽松的,在标志重复的情况下,不抛出任何异常。
示例:
function test(p,f){
try{
var r=new RegExp(p,f);
document.write(r.toString+/'<br>/');
}catch(e){
document.write(e.name+/':/'+e.message+/'<br>/');
}
}test(new RegExp(/'foo/'));//ok
test(new RegExp(/'foo/'),undefined);//ok
test(new RegExp(/'foo/'),/'gim/');//TypeError
test(/'foo/');//ok
test(/'foo/',undefined);//ok
test(undefined,/'gim/');//ok
test(/'foo/',/'gimgim/');//SyntaxError
test(/'foo/',/'pvl/');//SyntaxError
21.getYear日期原型
对于IE来说,Date.prototype.getYear类似于Date.prototype.getFullYear。
示例:
var d=new Date(/"10 July 2001/");
var y=d.getYear;
document.write(y+/'<br>/');
输出:
IE:2001
FF、Opera、Safari:101
22.setYear日期原型
对于IE来说,Date.prototype.setYear类似于Date.prototype.setFullYear。
示例:
var d=new Date(+0);
d.setYear(95);
y=d.getYear;
document.write(/"setYear:/"+y+/"/");
d.setFullYear(95);
y=d.getYear;
document.write(/"setFullYear:/"+y);
输出:
IE:setYear:95 setFullYear:95
FF、Opera、Safari:setYear:95 setFullYear:-1805