標籤:his 必須 更改 text 未使用 字元集 最小 scope cal
第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.0Math.round(.6)//向上求整,輸出1.0Math.ceil(.6)//向下求整,輸出0.0Math.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();//輸出2011later.getFullMonth;//輸出0,月份從0開始later.getFullDate();//輸出1later.getDay();//輸出5,星期五;0表示周日。later.getHours();//輸出時間
二、字串
文本字串是由一組16位值組成的不可變的有序序列。字串的下標索引從0開始。兩個字串的瞭解可以通過加號“+”運算子
msg="hello, "+"world";//輸出"hello, world"
字串的主要屬性和方法:
var s="hello, world"s.length //輸出12s.charAt(0)//輸出hs.charAt(s.length-1)//輸出ds.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/""(Null 字元串)會被轉換成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",臨時建立一個新Object Storage Services; //輸出"hello",並未改變
原始值的比較就是值的比較,只有在其值相等時才相等;其中對於兩個單獨的字串,若且唯若它們長度相等並且每個對應索引的字元都相等時,才相等。
而對象的比較並非值的比較,即便兩個對象包含同樣的屬性和對應相同的值,也不相等;對於兩個單獨的數組也是如此。只有當兩個對象引用的是同一個基底物件時,它們才相等。
var o={x:1}, p={x:1}; //建立了兩個單獨的對象o===p; //輸出false;兩個單獨的對象永不相等var a=[],b=[]; a===b; //輸出false;數組也與上述一樣//引用對象的情況var a=[]; //建立一個數組var b=a; //建立一個數組,引用avar c=a; //建立一個數組,引用ac[0]=1; //通過c來修改引用a[0]; //輸出1b[0]; //輸出1a===b; //truec===a; //trueb===c; //true
七、變數聲明
JavaScript中在使用一個變數之前應當先聲明:
var i;var a,b,c; //也可以同行一次聲明多個變數var m=1,s="hello",t;var n=10; //聲明建立一個基本數實值型別的變數nn="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; //返回falsedelete b; //返回truedelete c; //返回true
JavaScript權威指南(第6版)學習筆記一