讀古今文學網 > 編寫高質量代碼:改善JavaScript程序的188個建議 > 建議161:關注各種引擎對ECMAScript v3的補充 >

建議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]