這里所說的JavaScript指瀏覽器環境中的包括宿主環境在內的。
第一種是ECMAScript Global Object,第二種是宿主環境(Host)下的全局對象/函數。
一、核心JavaScript內置對象,即ECMAScript實現提供的不依賴於宿主環境的對象
這些對象在程序執行之前就已經(實例化)存在了。ECMAScript稱為The Global Object,分為以下幾種
1, 值屬性的全局對象(Value Properties of the Global Object)。有NaN,Infinity,undefined。
2, 函數屬性的全局對象(Function Properties of the Global Object)。有eval,parseInt,parseFloat,isNaN,isFinite,decodeURI,encodedURI,encodeURIComponent
3,構造器(類)屬性的全局對象(Constructor Properties of the Global Object)。有Object,Function,Array,String,Boolean,Number,Date,RegExp,Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError。
4,其它屬性的全局對象(Other Properties of the Global Object),可以看出成是Java中的靜態類,可以直接用類名+點號+方法名使用。有Math,JSON。
ECMAScript規范提到這些全局對象(The Global Object)是具有Writable屬性的,即Writable為true,枚舉性(Enumerable)為false,即不能用for in枚舉。ECMAScript有這么一段
Unless otherwise specified, the standard built-in properties of the global object have attributes {[[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}.
雖然規范提到The Global Object是可以被重寫的,但不會有誰去重寫它們的。這里僅僅做個測試。
1
2
3
4
5
6
7
8
9
|
NaN = 11;
eval = 22;
Object = 33;
Math = 44;
alert(NaN);
alert(eval);
alert(Object);
alert(Math);<br>
|
分別取值屬性的全局對象, 函數屬性的全局對象,構造器(類)屬性的全局對象,其它屬性的全局對象NaN,eval,Object,Math。結果如下
結果可以看出除了NaN在IE9(pre3)/Safari不能被重寫外,其它都被重寫了。這里只是列舉了四個,感興趣的可以將以上所有的The Global Object一一測試下。這里想表達的是核心JavaScript內置對象一般是可以被重寫的 ,雖然沒人這么干。
下面測試下其可枚舉性
1
2
3
4
5
6
7
8
9
10
11
12
|
for
(
var
a
in
NaN){
alert(a);
}
for
(
var
a
in
eval){
alert(a);
}
for
(
var
a
in
Object){
alert(a);
}
for
(
var
a
in
Math){
alert(a);
}
|
所有瀏覽器都沒有彈出,即屬性不被枚舉。感興趣的可以將以上所有的The Global Object的枚舉性一一測試下。當然對於有些瀏覽器如Firefox,某些Global Object被重寫后又是可以被枚舉的。
二、宿主環境提供的全局對象/函數
如window,alert,setTimeout,document,location等,多數瀏覽器都會限制其重寫
1
2
|
window = 55;
alert(window);
|
該句在IE下會出錯提示非法復制,后面的彈出框沒有執行。其它瀏覽器則當window=55不存在,仍然彈出了window。
再重寫下alert
1
2
|
alert = 55;
console.log(alert);
|
IE下提示報錯,Firefox/Chrome/Safari/Opera竟然被重寫了,從對應的控制台可以看到輸出了55。可以看出對於宿主環境提供的全局對象/函數,有的瀏覽器不支持重寫,有的則可以重寫 。
以下是兩種方式聲明全局變量
1
2
3
4
5
6
7
8
|
a1 = 11;
var
a2 = 22;
for
(a
in
window){
if
(a==
'a1'
||a==
'a2'
){
alert(a)
}
}
|
上述代碼在IE中不會彈出信息框,在IE中內部大概如下
1
2
3
4
5
6
7
|
//IE
with
(host_object){
//window
with
(global_object){
//Global
a1 = 11;
var
a2 = 22;
}
}
|
即a1,a2是作為上面說的第一種,JS引擎提供的Global對象上的屬性,而非第二種宿主環境提供的window對象上的屬性。因此IE中for in window時a1,a2都不存在。如果IE中提供對象Global對象的引用,沒准下面的代碼可以彈出信息框。
1
2
3
4
5
|
for
(a
in
Global){
if
(a==
'a1'
||a==
'a2'
){
alert(a)
}
}
|
Firefox/Safari/Chrome/Opera中內部大概是下面的樣子
1
2
3
4
5
6
7
|
//Firefox/Safari/Chrome/Opera
with(host_object){
//window
a1 = 11;
var a2 = 22;
with(global_object){
//Global
}
}
|
即a1,a2是作為上面說的第二種,宿主環境提供的全局對象window上的屬性。因此for in window時a1,a2都存在,彈出了信息框。
再看第三者方式聲明全局變量window.a3 = 33,這樣是顯示的把a3掛在window上作為window的屬性,因此在所有瀏覽器中for in window時都能獲取到a3。
全局對象是預定義的對象,作為 JavaScript 的全局函數和全局屬性的占位符。通過使用全局對象,可以訪問所有其他所有預定義的對象、函數和屬性。全局對象不是任何對象的屬性,所以它沒有名稱。
全局對象只是一個對象,而不是類。既沒有構造函數,也無法實例化一個新的全局對象。
頂層函數(全局函數)
FF: Firefox, N: Netscape, IE: Internet Explorer
函數 | 描述 | FF | N | IE |
---|---|---|---|---|
decodeURI() | 解碼某個編碼的 URI。 | 1 | 4 | 5.5 |
decodeURIComponent() | 解碼一個編碼的 URI 組件。 | 1 | 4 | 5.5 |
encodeURI() | 把字符串編碼為 URI。 | 1 | 4 | 5.5 |
encodeURIComponent() | 把字符串編碼為 URI 組件。 | 1 | 4 | 5.5 |
escape() | 對字符串進行編碼。 | 1 | - | 3 |
eval() | 計算 JavaScript 字符串,並把它作為腳本代碼來執行。 | 1 | 2 | 3 |
getClass() | 返回一個 JavaObject 的 JavaClass。 | |||
isFinite() | 檢查某個值是否為有窮大的數。 | 1 | 4 | 4 |
isNaN() | 檢查某個值是否是數字。 | 1 | 2 | 3 |
parseFloat() | 解析一個字符串並返回一個浮點數。 | 1 | 2 | 3 |
parseInt() | 解析一個字符串並返回一個整數。 | 1 | 2 | 3 |
unescape() | 對由 escape() 編碼的字符串進行解碼。 | 1 | - | 3 |
頂層屬性(全局屬性)
FF: Firefox, N: Netscape, IE: Internet Explorer
屬性 | 描述 | FF | N | IE |
---|---|---|---|---|
Infinity | 代表正的無窮大的數值。 | 1 | 4 | 4 |
java | 代表 java.* 包層級的一個 JavaPackage。 | |||
NaN | 指示某個值是不是數字值。 | 1 | 4 | 4 |
Packages | 根 JavaPackage 對象。 | |||
undefined | 指示未定義的值。 | 1 | 4 | 5.5 |
encodeURI()和encodeURIComponent()方法用於編碼傳遞給瀏覽器的URI(統一資源標識符)。有效的URI不能包含某些字符,如空格。這兩個方法用於編碼URI,這樣用專門的UTF-8編碼替換所有的非有效字符,就可以使瀏覽器仍能夠接受並理解它們。
encodeURI()方法用於處理完整的URI(例如,http://www.wrox.com/illegal value.htm),而encodeURIComponent()用於處理URI的一個片斷(如前面的URI中的illegal value.htm)。這兩個方法的主要區別是encodeURI()方法不對URI中的特殊字符進行編碼,如冒號、前斜杠、問號和英鎊符號,而encodeURIComponent()則對它發現的所有非標准字符進行編碼。例如:
var sUri = "www.sohu.com/abc def 我.aspx";
alert(encodeURI(sUri));
alert(encodeURIComponet(sUri));
這段代碼輸出兩個值:
www.sohu.com/abc%20def%20%E6%88%91.aspx
www.sohu.com%2Fabc%20def%20%E6%88%91.aspx
可以看到,除空格外,第一個URI無任何改變,空格被替換為%20。第二個URI中的所有非字母數字字符都被替換成它們對應的編碼,基本上使這個URI變得無用。這就是encodeURI()可以處理完整URI,而encodeURIComponent()只能處理附加在已有URI末尾的字符串的原因。
自然,還有兩個方法用於解碼編碼過的URI,即decodeURI()和decodeURIComponent()。如你所料,這兩個方法所做的恰與其對應的方法相反。decodeURI()方法只對用encodeURI()方法替換的字符解碼。例如,%20將被替換為空格,而%23不會被替換,因為它表示的是英鎊符號(#),encodeURI()並不替換這個符號。同樣的,decodeURIComponent()會解碼所有encodeURIComponent()編碼過的字符,意味着它將對所有的特殊值解碼。例如:
這段代碼輸出兩個值:
在這個例子中,變量uri存放的是用encodeURIComponent()編碼的字符串。生成的值說明了應用兩個解碼方法時會發生的事情。第一個值由decodeURI()輸出,把%20替換成空格。第二個值由decodeURIComponent()輸出,替換所有的特殊。
這些URI方法encodeURI()、encodeURIComponent()、decodeURI()和decodeURICom- ponent()代替了BOM的escape()和unescape()方法。URI方法更可取,因為它們會對所有Unicode符號編碼,而BOM方法只能對ASCII符號正確編碼。盡量避免使用escape()和unescape()方法。
alert(s);
window.location.href=s;