再讀《悟透javascript》之一、JavaScript基礎

引言
      編程世界只存在兩種基本元素:一個是數據、另一個是代碼。無論多麼複雜的程序,都是對數據和代碼間千絲萬縷的關係進行的操作。
 

 

一、迴歸簡單,JavaScript的數據類型
1.       簡單數據類型
1)       undefined:代表一切未知的事物,什麼也沒有(注意:typeof(undefined)也是undefined)
2)       null:有一個空間,但空間中沒有數據
3)       boolean:布爾類型
(1)    undefined,null,’’,0轉換爲布爾類型,結果都爲false,其它一切值轉換成布爾類型都爲true,例:alert(Boolean(undefined));

(2)     ===:全等,表示類型和值都要相等,例:alert("123"==123);alert("123"===123);
4)       number:數值類型
5)       string:字符串類型
 

 

2.       複雜數據類型,只有object類型
在JavaScript中不要被類所束縛,JavaScript沒有類的概念,因爲它已將類化爲無形與對象溶爲一體了,看下面的代碼:
        var life = {};

        for(life.age=0; life.age<3; life.age++){

            switch(life.age){

                case 0:life.body="卵細胞";

                       life.say=function(){alert("now i'm a "+this.body);}

                       break;

                case 1:life.body="小蝌蚪";

                              life.tail="尾巴";

                       life.say=function(){alert("now i'm a "+this.body);}

                       break;

                case 2:life.body="青蛙王子";

                              delete life.tail;

                              life.legs="腿";

                       life.say=function(){alert("now i'm a "+this.body);}

                       break;

            }

           

            life.say();

}
上面可以看到,一個life對象從卵細胞變成小蝌蚪再變成青蛙王子,是多麼的有趣,這就是JavaScript的魅力,life不是某個類的固定的實例化對象,它 是如此的靈活,並不侷限於某個固定的類;假如我們用面向對象的思想來編寫的話,會怎樣呢?那麼我們就需要建立三個類來反映life生命中的三個階段,然後再來編程,假如life對象有十個生命過程呢?my god那就要十個對象了,那再多一點~~~~~~,面向對象是爲了幫助我們理解問題解決問題的,當它成爲了我們的阻礙時,我們就要堅決地拋棄它。
 

 

3.       function,函數,程序之神
1)       靜態函數:function xxx(){…},如果在同一個程序段內,出現同名的靜態函數,那麼該函數將以最後位置的函數爲準。例:
<script type="text/javascript">
        function test(){alert("hello");}

        test();

        function test(){alert("hi~~~");}

test();

</script>
我們會看到,它兩次都彈出hi~~~,即最後位置的函數。
 

 

2)       動態函數:var xxx = function(){…},動態函數不存在靜態函數同名的問題,在程序執行到時,最後賦值的函數就是要調用的函數。例:
    <script type="text/javascript">

        var test = function(){alert("hello");}

        test();

        var test = function(){alert("hi~~~");}

        test();

</script>

這裏我們可以看到,程序先彈出hello,後彈出hi~~~,第一個test執行前賦值的是彈出hello的函數,而第二個test執行前賦值的是彈出hi~~~的函數。
 

 

3)       JavaScript是一段段地分析執行函數,而不是一行行地分析執行,如果將上面的靜態函數的例子拆成兩個程序段,就可以看出來,例:
<script type="text/javascript">
        function test(){alert("hello");}

        test();

</script>
<script type="text/javascript">
        function test(){alert("hi~~~");}

test();

</script>
可以看到,程序先輸出hello後輸出hi~~~,證明了JavaScript是一段段的執行的。
一段代碼中的靜態函數會優先執行,這一特徵被稱爲“JavaScript的預編譯”,事實上,JavaScript的預編譯還包括對所有var變量的創建(初始值爲undefined),用以提高對代碼的執行效率。(請注意此段話,後面會有示例)
 

 

二、變量、屬性、作用域
1.       任何程序都會在一個原始的環境中開始運行,這個原始的環境被稱爲“全局環境”,全局環境包含一些預定義的元素,這些元素對於我們的程序來說是自然存在的,我們直接拿來即可用,就像我們呼吸的空氣一樣。在JavaScript中,這個全局環境就是window對象。
 

 

2.       變量與屬性
1)       變量:var myName=”luo”;這裏聲明瞭一個變量
2)       屬性:myName=”soldierluo”;這裏定義了一個屬性
 

 

3.       變量的作用域只在函數體內,而屬性則沒這樣的限制,這樣的安排是JavaScript的一個極大的特點,請特別注意,例:
    <script type="text/javascript">

    var firstName = "luo";

    var lastName = "jun";

    fullName = "soldierluo";

    alert("firstName:"+firstName+" lastName:"+lastName+" fullName:"+fullName);

    function test(){

        alert("firstName:"+firstName+" lastName:"+lastName+" fullName:"+fullName);

        var firstName = "soldier";

           lastName = "kkk";

        fullName = "changed";

        alert("firstName:"+firstName+" lastName:"+lastName+" fullName:"+fullName);

    }

    test();

    alert("firstName:"+firstName+" lastName:"+lastName+" fullName:"+fullName);

</script>

上面這個例子非常有意思,程序總共彈出了四次,firstName由luo->undefined->soldier->luo;而lastName爲jun->jun->kkk->kkk;fullName則是soldierluo->soldierluo->changed->changed;
看來變量lastName和屬性fullName比較像呢!爲什麼同是變量的firstName反而更不同呢?因爲作用域,請看test函數中也聲明瞭一個firstName的變量,這樣它就會屏蔽父域中的同名變量,那爲什麼是undefined呢?看看上面標紅的關於JavaScript預編譯的那段話就清楚了,此時的firstName被預編譯設置成undefined,等到之後賦值爲soldier後再輸出就是soldier了。最後firstName怎麼又變成luo了呢?因爲test函數結束後,test函數中的變量就消失了,所以父域的變量又出現了,就這麼回事。
至於lastName和fullName,就不需要解釋了吧,他們都是正常的作用域內,規規矩矩的變化着。
看了上面的實例,應該比較清楚什麼時候用var了吧,如果使用var,那麼它就是一個臨時變量,函數結束後它就消失了,而全局變量和屬性則不會。所以,在函數中儘量使用var可以避免不必要的衝突,比如修改了父域的變量或屬性等等。
 

 

4.       caller對象,返回調用該函數的函數,如果爲null,則表示被全局函數調用,例:
    <script type="text/javascript">

    function test(){alert(test.caller);}

    function useTest(){test();}

    test();

    useTest();

</script>

 

 

5.       arguments對象,函數屬性,傳入參數的集合,例:
    <script type="text/javascript">

    function test(){alert(arguments.length);}

    function test_1(a,b,c){ alert(arguments.length); alert(arguments.length>0arguments[1]:-1);}

    test();

    test_1();

    test_1(1,6);

</script>
可以看到,arguments是實際傳入的參數的集合,與函數的定義無關,可以通過arguments[index]來訪問參數。
 

 

三、object&function,對象與函數
1.       如果我說函數和對象是一樣的,或者說函數就是對象,你一定會罵我sb,對象是實體,函數是行爲,怎麼可能一樣,其實你說的都不錯,但是,這是在JavaScript裏,事實上函數就是對象。例:
    <script type="text/javascript">

    function sing(){alert(sing.name+":"+sing.title);}

    sing.name = "李白";

    sing.title = "《關山月》";

    sing();

    sing.name = "白居易";

    sing.title = "《琵琶行》";

    sing();

</script>
可以看到sing作爲一個函數,我們卻可以直接爲它添加屬性,這不是對象的基本特徵嗎?通過上面的例子,我們可以很清楚地看到,在JavaScript中,函數的本質它就是對象,只不過它是特殊的可以被調用的對象。
 

 

2.       放下對象,找到自我
1)       this,就是自我,但是這個自我是誰呢?誰調用了函數,那麼這個函數的this就是這個誰誰誰(對象)了。例:
    <script type="text/javascript">

    function whoIam(){alert("i'm "+this.name);}

    var luo = {name:"luojun", say:whoIam};

    luo.say();

    var soldier = {name:"soldierluo", say:whoIam};

    soldier.say();

    luo.say.call(soldier);

    soldier.say.call(luo);

    ({name:"noName", say:whoIam}).say();

</script>
從這裏我們可以看到,誰調用了whoIam,whoIam中的this就是誰,如果是由window對象調用,那麼this就是window了。所以這個this是個很油頭的東西,有奶便是娘。
 

 

2)       在一般的對象語言中,方法體代碼中的this可以省略,因爲成員默認都首先是自己的。但JavaScript卻不同,由於有奶便是孃的特點,它沒有自己,它必須找到一個有奶的娘,它才知道自己是誰,所以如果要訪問自己下的屬性或方法時,this不能省略。例:
    <script type="text/javascript">

    name="luo";

    function whoIam(){alert("i'm "+this.name+" name:"+name);}

    var soldier = {say:whoIam};

    soldier.say();

</script>
我們看,soldier對象調用了whoIam函數,此時whoIam中的this就是soldier對象了,而soldier對象沒有定義name屬性,所以是應該訪問不到的,但是如果不用this的話,whoIam函數就是跑到它的祖先域中去查找name屬性,這自然不是我們要的結果,因爲我們的目的是訪問soldier對象的name屬性,所以不使用this來訪問自己的屬性或方法是會出現錯誤的。
 

 

四、對象素描,json是一種非常簡便的創建JavaScript對象的方法
1.       對象屬性定義在{}兩個大括號之間
2.       屬性是以鍵值對的方式呈現
3.       鍵值之間用:冒號分隔
4.       鍵值對之間用,逗號分隔
5.       如果是數組的話,使用[]中括號,值在中括號間
例:    <script type="text/javascript">

    var company = {

        name:"microsoft",

        say:function(){alert("i'm "+this.name+", most important product is "+ this.products[0]);},

        products:["windows","office","xbox"]

    };

    company.say();

</script>
怎樣?很是簡潔吧,json是JavaScript對象最好的系列化形式,它比xml更簡潔。我們還可以使用eval函數,直接將json轉換成一個JavaScript對象,這使得它成了ajax的寵兒。


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章