1、關于變量的聲名
大家都知道javascript是可以隱式聲名變量的。但要注意,隱式聲名變量總是被創建為全局變量。看以下代碼,情愿javascript語言強制聲明變量。建議大家一定要var聲明變量。
<SCRIPT LANGUAGE="JavaScript">
function test(){
??? var a=222;
?document.writeln(a);
}
test();
document.writeln(a);
</SCRIPT>

<SCRIPT LANGUAGE="JavaScript">
function test(){
??? a=222;
?document.writeln(a);
}
test();
document.writeln(a);
</SCRIPT>

2、關于變量的作用域
猜猜以下代碼輸出什么。
<SCRIPT LANGUAGE="JavaScript">
var x='000';
document.writeln(x);
a();
function a(){
??? var x='aaa';
?function b(){
???? document.writeln(x);
??????? var x='bbb';
??document.writeln(x);
?}
?b();
??? document.writeln(x);
}
</SCRIPT>
如果你的答案是?? 000 undefined bbb aaa。恭喜,ok.當代碼用到x變量時,先從函數塊(權威指南中用調用對象來解釋)中找,如果找不到,從上一級函數塊找,直到找到,如果知道頂層代碼(指var x='000';的位置)還沒找到定義,代碼會報未定義錯誤。

改一下代碼,得到 000 undefined 111 111
<SCRIPT LANGUAGE="JavaScript">
var x='000';
document.writeln(x);
a();
function a(){
?function b(){
???? document.writeln(x);
??document.writeln(x);
?}
?document.writeln(x);
?var x='111';
?b();?
}
</SCRIPT>
3、新的問題
變量個作用域清楚了,注意上面的代碼。為什么我的function a()定義以前就可以調用a函數了,而我的var x='111';前“不可以用”x啊???
讓我把我的理解一一道來
首先:以下代碼讓我相信javascript有個預編譯過程,不是完全按照順序解釋執行的。
<SCRIPT LANGUAGE="JavaScript">
a();
function a(){
??? alert();
}
</SCRIPT>

? 個人理解這個預編譯過程不會象java/c#那樣把代碼編譯成虛擬機認識的語言,更不會象vb,vc那樣編譯成更底層的語言。猜想只是把這個函數預裝載到這段函數執行的全局環境中,在這個執行環境中,該函數被標識定義過,可以直接使用了。(看到網上很多人寫的AOP的javascript實現,其實這個預編譯過程才是翻譯元數據最佳時候,可惜就javascript語言來講,是有些落伍了)

這個文章主要講變量的一些問題。變量說了,為什么函數可以,我變量就不可以呢。
<SCRIPT LANGUAGE="JavaScript">
document.writeln(a);
var a=0;
</SCRIPT>

為什么我要輸出undefined呢?為什么我a就不可以預編譯一把呢?
大家看看以下兩段代碼會輸出什么呢啊???
<SCRIPT LANGUAGE="JavaScript">
document.writeln(a);
a=0;
</SCRIPT>

<SCRIPT LANGUAGE="JavaScript">
document.writeln(a);
</SCRIPT>

可能你運行試了,可能你本來就知道,a未定義。哈哈哈,好了。
現在我確信var a=0;被javascript解釋器“預編譯過”,至少是記錄下來了。甚至把它的值設置為 undefined。“undefined”這個詞名字取的很是讓人誤解,怎么能叫未定義呢,分明是javascript中所有變量的初始化值。關于null與undefined的比較我實在不愿提了。
注意上面兩段代碼還反映一個現象。隱式聲明的變量是在解釋的時候才把自己定義為全局變量的。

關于函數與變量javascript預編譯的不同處理,大家可以與java class的加載過程比較下。java也是對基本類型設出值,對象為null的。(不往遠扯了)
4、區別未定義變量和未附值變量
<SCRIPT LANGUAGE="JavaScript">
var a;
document.writeln(a);
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript">
document.writeln(a);
</SCRIPT>
未定義變量和未附值變量?? 權威指南中文版 定義的。通過第三條分析,我覺得變量就應該以?? 定義和未定義變量區別。未附值變量和undefined有點沖突,javascript不是強類型語言,沒發附默認值,才來了個undefined。
5、基本類型和引用類型
熟悉java的朋友可能這部分很清楚。沒啥
說頭。
6、javascript的垃圾回收
關于這部分內容一直沒見著個權威說法。在javascript權威指南中有兩小節提到這個問題。
對于字符串、對象、數據這些沒有固定大小,必須為它們動態的分配內存,但什么時候回收這些內存呢?javascript使用和java一樣的garbage collection的方法。
var s="hello";
var u=s.toUpperCase();
s=u;

運行這段代碼后,"hello"沒有變量會再用到他,這是"hello"的存儲空間的被垃圾回收了。對于javascript的垃圾回收,你唯一要關心的是,它一定會進行,不要對內存擔心。
注意,javascript不提供任何的強制垃圾回收或釋放內存的運算附或語句。
javascript的delete運算附和C++中的不同。
<SCRIPT LANGUAGE="JavaScript">
var o=new Object();
o.name="zkj";
o.age=25;
o.bir=new Date();
for(var key in o){
document.writeln(key+':'+o[key]+'</br>');
}
document.writeln('delete o.bir</br>');
delete o.bir;
for(var key in o){
document.writeln(key+':'+o[key]+'</br>');
}
</SCRIPT>
7、作為屬性的變量
猜猜以下代碼會輸出什么。
<SCRIPT LANGUAGE="JavaScript">
var x=100;
document.writeln(x);
add(x);
document.writeln('</br>------------------------</br>');
var x=200;
document.writeln(x);
add(x);
function add(x){
??? document.writeln(x);
??? var x=300;
??? document.writeln(x);
??? var x=400;
??? document.writeln(x);
}
</SCRIPT>
估計很多人能得出正確答案
100 100 300 400
------------------------
200 200 300 400
但這里我想引入? 全局對象和調用對象的 概念(javascript權威指南是這么翻譯滴)
<SCRIPT LANGUAGE="JavaScript">
var x=100;?? //我們在全局對象中加了個屬性x. 對比
?//var o=new Object();o.x=100;
document.writeln(this.x);//用this訪問全局對象
add(this.x);//把全局對象的屬性值傳遞對函數中
document.writeln('</br>------------------------</br>');
this.x=200;//把全局變量中的x屬性修改掉
document.writeln(window.x);
add(window.x);
function add(x){
??? //假設有個局部對象,調用對象,函數調用過程中的對象
//? temp?? temp.x=${傳入的值}
??? document.writeln(x); //哦這打印的可是參數中的值,也就是temp.x=this.x
//的值,
??? var x=300;//把調用對象變量的簽名給覆蓋了.
??? document.writeln(x); //打印修改過的值。 temp.x
?var x=400;//temp.x=400
??? document.writeln(x);
}
</SCRIPT>

在函數的調用過程中,假設有個調用對象存在,把函數的參數,和函數內的臨時變量當成這個調用對象的屬性。當然這個調用對象的生命周期很短。
注意,當我們訪問全局變量的屬性入x的時候,不必要用this.x 或window.x訪問,當在有<frame><iframe>的頁面時會出現混淆。
關于函數的詳細討論我后續會詳細討論。