首页 » 编写高质量代码:改善JavaScript程序的188个建议 » 编写高质量代码:改善JavaScript程序的188个建议全文在线阅读

《编写高质量代码:改善JavaScript程序的188个建议》建议161:关注各种引擎对ECMAScript v3的补充

关灯直达底部

1.数值类型

ECMAScript v3提供了检测各种NaN值的方法,而IE没有提供任何方法来检测各种NaN值。

2.数值类型的字符串应用

ECMAScript v3规范提供了浮点数转换成字符串的精度表示,但最终显示结果将依赖于实现的代理设备。代表浮点数作为一个字符串时,IE支持16位精度。而其他引擎与IE略有不同,下面通过一个示例进行比较。


var x=0x8000000000000800;

document.write(x,/"/");

var y=9223372036854777856;

document.write(y);


输出:


IE:

9223372036854777000 9223372036854777000

FF、Opera、Safari:

9223372036854778000 9223372036854778000


3.typeof运算符

在使用typeof运算符检测宿主对象的类型时,将依赖于实现引擎返回不同的值。

示例:


alert(typeof(window.alert));


输出:


IE:object

FF、Opera、Safari:function


不过下面的用法在IE中将抛出异常,而其他引擎返回45。


var a=window.alert;a.apply(null,[45]);


4.for in语句

ECMAScript v3规范的枚举依赖于实现属性的机制。在IE中,在列举属性时,以相反的顺序枚举原型属性(相对于在其中被添加的顺序),按顺序枚举当前对象的属性,其余对象的属性按原型链中的顺序枚举。

示例:


function dough{

this.da=/"da/";

this.db=/"db/";

this.dc=/"dc/";

}

bread.prototype=new dough;

function bread{

this.ba=/"ba/";

this.bb=/"bb/";

this.bc=/"bc/";

}

pizza.prototype=new bread;

function pizza{

this.pa=/"pa/";

this.pb=/"pb/";

this.pc=/"pc/";

}

function getProperties(obj,objName){

var res=/"/";

for(var i in obj){

res+=objName+/"./"+i+/"=/"+obj[i]+/"<br>/";

}

return res;

}

var p=new pizza;

document.write(getProperties(p,/"pizza/"));


输出:


IE:

pizza.bc=bc

pizza.bb=bb

pizza.ba=ba

pizza.da=da

pizza.db=db

pizza.dc=dc

pizza.pa=pa

pizza.pb=pb

pizza.pc=pc

FF、Opera、Safari:

pizza.pa=pa

pizza.pb=pb

pizza.pc=pc

pizza.ba=ba

pizza.bb=bb

pizza.bc=bc

pizza.da=da

pizza.db=db

pizza.dc=dc


5.对象连接

当不同变量连接对象时,由于实现的差异,运行结果可能也会不同。

考虑下面的示例:


function foo{

function bar{}

return bar;

}

var x=foo;

var y=foo;

x.blah=1;

y.blah=2;

document.write(x.blah+y.blah);


上面代码的输出值为3,但另一种实现的输出值为4,这种实现也符合标准。

6.函数创建

与标准不同,IE使用最后一次出现的函数声明定义函数。

示例:


if(true){

function bar{

document.write(/"bar1/");

}

}else{

function bar{

document.write(/"bar2/");

}

}

bar;

function foo{

if(true){

function baz{

document.write(/"baz1/");

}

}else{

function baz{

document.write(/"baz2/");

}

}

baz;

}

foo;


输出:


IE:bar2 baz2

FF、Opera、Safari:

bar1 baz1


7.eval方法

ECMAScript v3规范不允许通过其他变量间接调用全局函数eval,否则将抛出一个EvalError异常,但IE、FF、Safari引擎允许间接调用eval。

示例:


var sum=eval(/"1+2/");

alert(sum);

var myeval=eval;

try{

sum=myeval(/"1+2/");

alert(sum);

}catch(e){

alert(/"indirect eval not supported!/");

}


输出:


IE、FF、Safari:3 3

Opera:3/"indirect eval not supported/"


8.parseInt方法

当基数为0,或者未定义的字符串值以0开始,后面不是x或X时,这个数值可根据不同的实现转换为八进制或十进制的数字。IE和FF、Safari引擎会把它解释为八进制数字。

示例:


alert(parseInt(/"08/",undefined));

alert(parseInt(/"08/",0));

alert(parseInt(/"011/",undefined));

alert(parseInt(/"011/",0));


输出:


IE、FF、Safari:

0,0,9,9

Opera:8,8,11,11


9.toString函数原型

当使用toString函数原型来处理其他函数中的空白时,IE将忽略换行符和Tab空格,而FF、Opera和Safari浏览器忽略换行符,这些浏览器有一个细微的差别。

示例:


function foo{

var e={

name:/"value/",

id:11

};

return e;

}

alert(foo.toString.indexOf(/',/'));


输出:


IE:45

FF:42

Opera:43

Safari:45


10.对象构造器和宿主对象

当使用Object构造器构建宿主对象时,IE把它视为一个object对象,而其他引擎把它视为一个DOM对象。

示例:


alert(new Object(window.document));


输出:


IE:[object]

FF、Safari、Opera:[object HTMLDocument]


11.宿主对象的值

当使用valueOf方法读取宿主对象的值时,IE将会抛出错误。

示例:


var x=new Object(window.document);

alert(x.valueOf);


输出:


IE:抛出运行时错误(object doesn’t support this property or method)

FF、Safari、Opera:[object HTMLDocument]


12.toLocaleString数组原型

不同引擎对于toLocaleString方法的返回值是不同的。

示例:


var n=Number(123456789.00);

var d=new Date;

var t=new Date.getTime;

var s=/"hello world/";

var a=new Array;

a.push(n);

a.push(d);

a.push(d);

a.push(s);

document.write(a.toString+/"<br>/");

document.write(a.toLocaleString+/"<br>/");


输出:


IE:

123456789,Fri Jul 13 01:13:45 UTC+0530 2007,Fri Jul 13 01:13:45 UTC+0530 2007,hello world

123,456,789.00,Friday,July 13,2007 1:13:45 AM,Friday,July 13,2007 1:13:45 AM,hello world

FF

123456789,Fri Jul 13 2007 01:14:50 GMT+0530(India Standard

Time),Fri Jul 13 2007 01:14:50 GMT+0530(India Standard Time),hello world

123,456,789,Friday,July 13,2007 1:14:50 AM,Friday,July 13,2007 1:14:50 AM,hello world

Opera:

123456789,Fri,13 Jul 2007 01:16:07 GMT+0530,Fri,13 Jul 2007

01:16:07 GMT+0530,hello world

123456789,7/13/2007 1:16:07 AM,7/13/2007 1:16:07 AM,hello world

Safari

123456789,Fri Jul 13 2007 01:16:24 GMT+0530(India Standard Time),Fri Jul 13 2007 01:16:24 GMT+0530(India Standard Time),hello world

123456789,Friday,July 13,2007 01:16:24,Friday,July 13,2007 01:16:24,hello world


13.Number构造器

IE和Opera会把所有字符串带有负号的十六进制数字转换为NaN,而其他引擎会把它转换为负数。

示例:


alert(/'Number(/"0x10/")==/'+Number(/"0x10/"));

alert(/'Number(/"-0x10/")==/'+Number(/"-0x10/"));


输出:


IE、Safari:16,NaN

FF、Opera:16,-16


14.toString数值原型

当使用无效的基数时,IE将抛出一个TypeError异常。

示例:


var val=42;

document.write(/'val.toString==/'+val.toString+/'<br>/');

document.write(/'val.toString(2)==/'+val.toString(2)+/'<br>/');

document.write(/'val.toString(8)==/'+val.toString(8)+/'<br>/');

document.write(/'val.toString(16)==/'+val.toString(16)+/'<br>/');

document.write(/'val.toString(36)==/'+val.toString(36)+/'<br>/');

try{

document.write(/'val.toString(100)==/'+val.toString(100)+/'<br>/');

}catch(e){

document.write(/'Invalid Radix Error:/'+e.name+/':/'+e.message+/'<br>/');

}

document.write(/'val.toString==/'+val.toString+/'<br>/');

try{

document.write(/'val.toString(undefined)==/'+val.toString(undefined)+/'<br>/');

}catch(e){

document.write(/'Invalid Radix Error:/'+e.name+/':/'+e.message+/'<br>/');

}


输出:


IE:

val.toString==42

val.toString(2)==101010

val.toString(8)==52

val.toString(16)==2a

val.toString(36)==16

Invalid Radix Error:TypeError:Invalid procedure call or argument

val.toString==42

Invalid Radix Error:TypeError:Invalid procedure call or argument

FF:

val.toString==42

val.toString(2)==101010

val.toString(8)==52

val.toString(16)==2a

val.toString(36)==16

Invalid Radix Error:Error:illegal radix 100

val.toString==42

Invalid Radix Error:Error:illegal radix 0

Opera、Safari:

val.toString==42

val.toString(2)==101010

val.toString(8)==52

val.toString(16)==2a

val.toString(36)==16

val.toString(100)==42

val.toString==42

val.toString(undefined)==42


15.UTC日期对象

在IE和FF浏览器中,如果UTC日期对象只是作为参数调用,那么返回一个数字,代表在这一年的1月1日的当前语言环境。

示例:


document.write(Date.UTC(1995));


输出:


IE、FF:788918400000

Opera:syntax error

Safari:NaN


16.toString日期原型

IE将使用UTC进行日期字符串转换。

示例:


var d=new Date(/"4 July 1776/");

document.write(d.toString);


输出:


IE:Thu Jul 4 00:00:00 UTC+0530 1776

FF、Safari:Thu Jul 04 1776 00:00:00 GMT+0530(India Standard Time)

Opera:Thu,04 Jul 1776 00:00:00 GMT+0530


17.toDateString日期原型

使用toDateString方法,不同引擎返回的字符串信息是不同的。

示例:


var d=new Date(/"July 10 1995/");

document.write(d.toDateString);


输出:


IE、FF、Safari:Mon Jul 10 1995

Opera:Mon,10 Jul 1995


18.toTimeString日期原型

使用toTimeString方法,不同引擎返回的字符串信息是不同的。

示例:


var d=new Date(/"July 10 1995/");

document.write(d.toTimeString);


输出:


IE:00:00:00 UTC+0530

FF、Safari:00:00:00 GMT+0530(India Standard Time)

Opera:00:00:00 GMT+0530


19.toLocaleString日期原型

使用toLocaleString方法,不同引擎返回的字符串信息是不同的。

示例:


var d=new Date(/"July 10 1995/");

document.write(d.toLocaleString);


输出:


IE、FF:Monday,July 10,1995 12:00:00 AM

Opera:7/10/1995 12:00:00 AM

Safari:Monday,July 10,1995 00:00:00


20.toLocaleDateString日期原型

使用toLocaleDateString方法,不同引擎返回的字符串信息是不同的。

示例:


var d=new Date(/"July 10 1995/");

document.write(d.toLocaleDateString);


输出:


IE、FF:Monday,July 10,1995

Opera:7/10/1995

Safari:same as IE


21.toLocaleTimeString日期原型

使用toLocaleTimeString方法,不同引擎返回的字符串信息是不同的。

示例:


var d=new Date(/"July 10 1995/");

document.write(d.toLocaleTimeString);


输出:


IE、FF、Opera:12:00:00 AM

Safari:00:00:00


22.toUTCString日期原型

使用toUTCString方法,不同引擎返回的字符串信息是不同的。

示例:


var d=new Date(/"July 10 1995/");

document.write(d.toUTCString);


输出:


IE:Sun,9 Jul 1995 18:30:00 UTC

FF、Opera、Safari:Sun,09 Jul 1995 18:30:00 GMT


23.toString正则表达式原型

当使用RegExp构造正则表达式对象时,如果传递的参数为空、未定义或/,则不同引擎返回对象的字符串值是不同的。

示例:


document.write(new RegExp.toString+/'<br>/');

document.write(new RegExp(undefined).toString+/'<br>/');

document.write(new RegExp(/"//").toString+/'<br>/');


输出:


IE、Opera、Safari:

//

//

///

FF:

/(?:)/

/undefined/

///


24.message错误原型

在IE、FF中,默认错误信息是一个空字符串,如果明确将未定义值作为参数信息,则将初始值设置为undefined。

示例:


function test(e){

document.write(/'e.message:/'+e.message+/'<br>/');

}

test(new Error);

test(new Error(undefined));


输出:


IE、FF:

e.message:

e.message:undefined

Opera:

e.message:Generic error

e.message:undefined

Safari:

e.message:Unknown error e

.message:Unknown error


25.toString错误原型

不同引擎对于错误对象的字符串返回值是不同的。

示例:


function test(e){

document.write(/'e.toString:/'+e.toString+/'<br>/');

}

test(new Error);

test(new Error(undefined));

test(new Error(/'Complex error/'));


输出:


IE:

e.toString:[object Error]

e.toString:[object Error]

e.toString:[object Error]

FF:

e.toString:Error

e.toString:Error:undefined

e.toString:Error:Complex error

Opera:

e.toString:[Error:name:Error message:Generic error]

e.toString:[Error:name:Error]

e.toString:[Error:name:Error message:Complex error]

Safari:

e.toString:Error:Unknown error

e.toString:Error:Unknown error

e.toString:Error:Complex error


26.message本地错误原型

不同错误类型的默认抛出信息是不同的。

示例:


document.write(new EvalError.message+/'<br>/');

document.write(new RangeError.message+/'<br>/');

document.write(new ReferenceError.message+/'<br>/');

document.write(new SyntaxError.message+/'<br>/');

document.write(new TypeError.message+/'<br>/');

document.write(new URIError.message+/'<br>/');


输出:


IE、FF:输出皆为空

Opera:

Use of eval as a value

Illegal manipulation of array or string length

Undefined variable or property

Mis-constructed program text

Incorrect value to a primitive operation

Generic error in a URI

Safari:

EvalError

RangeError

ReferenceError

SyntaxError

TypeError

URIError


27.错误对象

如果值、对象、属性等超出ECMAScript v3规范中所描述的功能,那么可能会导致返回一个结构。例如,寻找一个在全局范围内的变量,而不是抛出一个错误(如ReferenceError),可以降低互操作性。

示例:


var x={};

x.__proto__=3;

document.write(x.__proto__);


输出:


IE、Opera、Safari:3

FF:[object Object]