1. 程式人生 > >JavaScript權威指南(第6版)學習筆記一

JavaScript權威指南(第6版)學習筆記一

未定義 顯示 註釋 星期 語句 布爾運算 垃圾 class ron

第2章 詞法結構

一、字符集

*JavaScript程序是用Unicode字符集編寫的。

*JavaScript嚴格區分大小寫。

*JavaScript註釋:(1)“//”用於單行註釋;(2)"/* .... */"用於多行註釋。

*JavaScript使用分號將語句之間分隔;如果各條語句單獨成一行,通常可以省略分號。但下面幾種情況需要註意:

a = 3;  //這裏的分號是可以省略的
b = 4;

a = 3;  b = 4;   //這裏第一個分號不能省略

如果編寫時候未用分號,則JavaScript會自動填補分號,但只在缺少了分號無法正確解析代碼的時候。

var y = x + f 
(a
+b).toString() //對於以上代碼解析自動添加分號後如下 var y = x + f(a+b).toString(); //已經不是原意了
x
++
y

//解析自動添加後

x; ++y;

所以,添加分號是很好的編寫習慣。

第3章 類型、值和變量

*JavaScript的數據類型分為兩類:原始類型(primitive type)和對象類型;其中原始類型包括數字、字符串、布爾值、null(空)、undefined(未定義);JavaScript的對象是“命名值”的無序集合,是隸屬於該對象(Obeject)的屬性(property)的集合,每個屬性都由“名/值對”(這裏的值可以是原始類型數據,也又可以是對象類型數據);JavaScript還定義了數組(array)和函數等特殊對象。

*JavaScript解釋器有自己的內存管理機制,可以自動對內存進行垃圾回收(garbage collection),當程序中不再有任何引用指向一個對象時,解釋器就會自動回收該對象所占據的內存空間。

*從另外一個角度,JavaScript數據類型又可以分為可變類型和不可變類型。可變類型的值是可以修改的,如數組、對象。而數字、布爾值、null和undefined屬於不可變類型。

一、數字

*JavaScript不區分整數和浮點數,所有的數字都是用浮點數來表示。當一個數字直接出現在程序中,則稱為數字直接量(numeric literal)。

*JavaScript可以自由地進行數據類型轉換

*JavaScript中定義了Math對象,其屬性和方法定義了很多算術運算:

//求2的53次冪
Math.pow(2,53)
//
四舍五入,輸出1.0 Math.round(.6) //向上求整,輸出1.0 Math.ceil(.6) //向下求整,輸出0.0 Math.floor(.6) //返回最大值 Math.max(x,y,z) //返回最小值 Math.min(x,y,z) //生成一個0和1之間的偽隨機數 Math.random() //3的平方根 Math.sqrt(3) //e的三次冪 Math.exp(3)

在JavaScript中算術運算的溢出情況不會報錯,無窮大用Infinity表示,負無窮大用-Infinity表示。

換,其變量是無類型的,在聲明後可以被賦予任何類型的值。

*日期和時間:

var then= new Date(2011,0,1) ;  //2011年1月1日
var later=new Date(2011,0,1,17,10,30);
var now=new Date(); //當前日期時間
later.getFullYear();//輸出2011
later.getFullMonth;//輸出0,月份從0開始
later.getFullDate();//輸出1
later.getDay();//輸出5,星期五;0表示周日。
later.getHours();//輸出時間

二、字符串

文本字符串是由一組16位值組成的不可變的有序序列。字符串的下標索引從0開始。兩個字符串的了解可以通過加號“+”運算符

msg="hello, "+"world";//輸出"hello, world"

字符串的主要屬性和方法:

var s="hello, world"
s.length    //輸出12
s.charAt(0)//輸出h
s.charAt(s.length-1)//輸出d
s.substring(1,4) //輸出第2-4個字符
s.slice(-3)//輸出最後三個字符
s.indexOf("l")//輸出2,字符l首次出現的位置
s.lastIndexOf("l")//輸出10,字符最後一次出現的位置
s.indexOf("l",3)//輸出3,字符在位置3及之後首次出現的位置
s.split(", ")//["hello","world"],分割成子串
s.replace("h","H")//替換,輸出"Hello, world"
s.toUpperCase()//輸出"HELLO, WORLD"

在JavaScript中字符串是固定不變的,上面的replace()和toUpperCase()方法實際返回的是新創建的字符串。

三、布爾值

*布爾值只有兩個值:true和false。通常比較語句的返回值都是布爾值。如"a==4"用來監測a的值是否等於4。

*任意JavaScript的值都可以轉換為布爾值。undefined/null/0/-0/NaN/""(空字符串)會被轉換成false。其他所有值,包括對象(數組)都會被轉換成true。

*布爾運算:邏輯與&&/邏輯或||/布爾非NOT。

四、全局對象

當JavaScript解釋器啟動時(或者任何Web瀏覽器加載新頁面的時候),將創建一個新的全局對象,並給它一組定義的初始屬性:全局屬性如undefined、Infinity和NaN;全局函數,如IsNaN()、parsInIt()等;構造函數如Date()、RegExp()等;全局對象如Math等。

在客戶端JavaScript中,在其表示的瀏覽器窗口中的所有JavaScript代碼中,Window對象充當了全局對象,這個對象有一個屬性window引用其自身,可以代替this來引用全局對象。如果代碼又聲明了一個全局變量,那這個全局變量則是全局對象的一個屬性。

五、包裝對象

var s="hello world";
var word=s.substring(s.indexOf(" ")+1,s.length);

這裏s是字符串,而非對象,但還是可以有屬性,這裏是因為當引用了字符串的屬性時JavaScript會自動調用new String()的方法轉換成對象。同理,在對數字和布爾值類似場景時也會通過Number()和Boolean()構造函數創建對象。

需要註意的是,一旦屬性引用結束,這個新創建的對象就會銷毀。

var s="test";    //創建一個字符串
s.len=4;           //給其設置一個屬性
var t=s.len;      //創建變量t

在上述代碼中,最終t的值是undefined。在第二行代碼後,臨時創建的第二行代碼的包裝對象具備了len這個屬性(註意不是本身自帶的length屬性!)已經被銷毀,在第三行繼續創建一個新的包裝對象,這個對象是不具備len屬性的。

對於基於原始值創建的包裝對象,“==”是成立的,但全等“===”不成立。通過“typeof”運算符可以看出類型的不同。

六、不可變的原始值和可變的對象引用

JavaScript中的原始值(數字、布爾值、字符串、null、undefined)與對象有著根本區別,即他們是不可改變的,任何方法都無法更改一個原始值。對於undefined、null、數字和布爾值,這點很好理解。但對於字符串會顯得不夠明顯,總會認為可以將其視為數組似的對象,從而改變其中字符值。實際上,JavaScript禁止如此。字符串的方法修改的字符串實際返回的是一個修改後新的字符串。

var s="hello";
s.toUppercase();  //這裏返回"HELLO",臨時創建一個新對象存儲
s;       //輸出"hello",並未改變

原始值的比較就是值的比較,只有在其值相等時才相等;其中對於兩個單獨的字符串,當且僅當它們長度相等並且每個對應索引的字符都相等時,才相等。

而對象的比較並非值的比較,即便兩個對象包含同樣的屬性和對應相同的值,也不相等;對於兩個單獨的數組也是如此。只有當兩個對象引用的是同一個基對象時,它們才相等。

var o={x:1}, p={x:1};  //創建了兩個單獨的對象
o===p;        //輸出false;兩個單獨的對象永不相等
var a=[],b=[];  
a===b;        //輸出false;數組也與上述一樣

//引用對象的情況
var a=[];     //創建一個數組
var b=a;      //創建一個數組,引用a
var c=a;      //創建一個數組,引用a
c[0]=1;       //通過c來修改引用
a[0];           //輸出1
b[0];           //輸出1
a===b;       //true
c===a;       //true
b===c;       //true

七、變量聲明

JavaScript中在使用一個變量之前應當先聲明:

var i;
var a,b,c;   //也可以同行一次聲明多個變量
var m=1,s="hello",t;

var n=10;  //聲明創建一個基本數值類型的變量n
n="love";   //也可以靈活轉變其數據類型

八、變量作用域

一個變量的作用域(scope)是程序源代碼中定義這個變量的區域。全局變量擁有全局作用域;在函數內聲明的變量只在函數體內有效,是局部變量;函數的參數也是局部變量。

在函數體內部,局部變量的優先級高於同名的全局變量。如果在函數內聲明的一個局部變量或者函數參數中帶有的變量和全局變量重名,則全局變量在函數內會被局部變量覆蓋。

var scope="global";   //聲明一個全局變量
function checkscope() {
    var scope="local";       //函數體內的局部變量
    return scope;
}
checkscope();         //返回“local”

需要註意,如果給一個未聲明的變量賦值,JavaScript實際會給全局對象創建一個同名屬性,使其看起來像一個全局變量。因此,雖然在全局作用域內可以不聲明創建一個全局對象,但在聲明局部變量時必須使用var語句:

scope="global";  //創建一個全局變量
function checkscope2() {
    scope="local";   //這裏未使用“var”,則解釋器認為是上述的全局變量
    myscope="local";  //未使用"var",則創建了一個全局變量
    return [scope,myscope];  //返回兩個值
}
checkscope2();  //返回["local","loacl"]
scope;  //返回"local"
myscope; //返回"local"

局部作用域嵌套的情況:

var scope="global scope";  //全局變量
function checkscope(){
    var scope="loacl scope";  //局部變量
    function nested() {
        var scope="nested scope";  //嵌套作用域內的局部變量
        return scope;     //返回當前作用域內的值
    }
    return nested();
    }
checkscope();

*在類似C語言等編程語言中,花括號內的每一段代碼都具有自己的作用域,在其內聲明的變量對外是不可見的,這是塊級作用域(block scope);但在JavaScript中使用的是函數作用域(function scope):變量在聲明它的函數體以及這個函數體內嵌套的任意函數體內都是可見的。所以在一個函數體內,不管在什麽位置聲明的變量,甚至在它被聲明之前的語句也可以使用它(不會提示報錯),但只有在它被聲明以及賦值的位置之後才可以正確的使用它被賦予的值。因此,一般情況下,較好的習慣是在函數體中把要聲明的局部變量放在函數體頂部。

var scope="global";
function f() {
    //輸出“undefined”,可見的是後面聲明的局部變量,而非全局變量
    //但因為這個局部變量還沒有賦值    
    console.log(scope);  
    //局部變量在這裏賦值,但在函數體內任何位置都可見   
    var scope="local";  
    console.log(scope);   //輸出“local”
}

*對於全局變量的隱式和顯示聲明的區別就是,顯式使用var語句聲明的全局變量是不可刪除的,而隱式聲明的可以刪除。

var a=1; //聲明一個不可刪除的全局變量
b=2;  //創建全局對象一個可以刪除的屬性
this.c=3;   //同上,可以刪除
delete a;   //返回false
delete b;   //返回true
delete c;   //返回true

JavaScript權威指南(第6版)學習筆記一