最近正在看《JavaScript高級程序設計》,一直沒來得及總結一下,順便對以前看的《JavaScript DOM編程藝術》進行一些簡單的總結,若有一些不正確的地方還請多指出討論。javascript
在學習 JavaScript 以前要理解的第一個概念就是在 ECMAScript 中全部的一切(變量、函數名和操做符)都是區分大小寫的。好比變量 test 和 Test 是兩個不一樣的變量,typeof 不能用在函數名上,由於它是一個關鍵字,但 typeOf 徹底能夠是一個函數名,由於在 ECMAScript 中變量、函數名和操做符等等都是區分大小寫的。java
在學習以前還須要瞭解的第二個概念就是「標識符」,所謂標識符就是指變量、函數、函數的參數和屬性的名字,標識符能夠下列格式規則組合起來的一個或多個字符:正則表達式
按照慣例,ECMAScript 標識符采用駝峯大小寫格式,也就是第一個字母小寫,剩下的每一個單詞的首字母大寫,例如:編程
ECMAScript 中有 5 種基本數據類型:Undefined、 Null、 Boolean、 String 和 Number。還有 1 種複雜數據類型:Obect,Object 本質上是由一組無序的名值對組成。ECMAScript 不支持任何建立自定義類型的機制,而全部值最終都將是上述 6 種數據類型之一。瀏覽器
因爲 ECMAScript 是鬆散類型的,因此須要有一種方法來檢測給定變量的數據類型,typeof 就是負責提供這方面信息的操做符。對一個值使用 typeof 操做符可能返回下列某個字符串:函數
例如:學習
var message = "Some Message!" alert(typeof message); // "string" alert(typeof(message)); // "string" alert(typeof 95); // "number"
由此能夠看出 typeof 操做符的操做數能夠是變量(message),也能夠是數值字面量。注意,typeof 是一個操做符而不是函數,因此例子中的圓括號儘管可使用,但不是必需的。測試
這裏須要注意一下的是,若是對 null 進行 typeof 操做的話,會返回 "object",由於 null 會被認爲是一個空的對象引用。還有一些比較奇怪的返回值,好比 Safari 5 及以前的版本、 Chrome 7 及以前的版本在對正則表達式調用 typeof 操做符時會返回 "function",而在其餘瀏覽器下則會返回 "object"。設計
Undefined 類型的值只有一個,即特殊的 undefined。當用 var 關鍵字聲明一個變量但未對它進行初始化時,這個變量的值就是 undefined,例如:指針
var message; alert(message == undefined); // true
這個例子只對 message 進行了聲明,但未對其進行賦值操做,此時 message 的值就是 undefined,這個例子和下面這個例子是等價的:
var message = undefined; alert(message == undefined); // true
這個例子使用 undefined 值顯式初始化了變量 message。但咱們沒有必要這麼作,由於未經初始化的值默認就會取得 undefined 值。
對於 Undefined 類型還有一點須要注意的就是,聲明瞭變量可是未對其進行初始化賦值操做和根本就沒有聲明變量是不一樣的:
var message; // 聲明變量後默認取得 undefined // 下面這個變量根本沒有聲明 // var age; alert(message); // undefined alert(age);// Uncaught ReferenceError: age is not defined
對於第一個警告框你們確定沒疑問,彈出的應該是 "undefined",因爲傳遞給第二個警告框的是一個未申明的變量,因此在這裏會致使一個錯誤。
對於還沒有申明的變量,只能對其進行一項操做,即便用 typeof 對其進行數據類型的判斷。不過有一點比較奇怪的就是,對未進行初始化賦值操做的變量和未申明的變量使用 typeof 操做符,都會返回 "undefined":
var message; // 聲明變量後默認取得 undefined // 下面這個變量根本沒有聲明 // var age; alert(typeof message); // "undefined" alert(typeof age); // "undefined"
結果代表對未進行初始化賦值操做的變量和未申明的變量使用 typeof 操做符,都會返回 "undefined"。
Null 類型是第二個只有一個值的數據類型,這個特殊的值是 null。從邏輯角度來看,null 值表示一個空對象指針,而這也正是使用 typeof 操做符檢測 null 值時會返回 "object" 的緣由,以下面的例子所示:
var car = null; alert(typeof car); // "object"
若是定義的變量準備在未來用於保存對象,那麼最好將該變量初始化爲 null 而不是其餘值。這樣一來,只要直接檢查 null 值就能夠知道相應的變量是否已經保存了一個對象的引用,以下面的例子所示:
if (car != null){ // 對 car 對象執行某些操做 }
實際上,undefined 值是派生自 null 值的,所以 ECMA-262 規定對它們的相等性測試要返回 true:
alert(null == undefined); //true
這裏有一點也要注意的是,這裏的相等操做符(==)出於比較的目的,會對比較的兩個類型進行類型轉換(後面會對這個知識點進行一些詳細的總結)。
儘管 undefined 派生自 null,但它們的用途卻不相同,不管在什麼狀況下都沒有必要對一個變量的值顯示的賦值爲 undefined,而一樣的道理對 null 卻不適用,換句話說,只要意在保存對象的變量尚未真正的保存對象,就應該明確地地讓該變量保存 null 值。這樣作不只能夠體現 null 做爲空對象指針的慣例,也有助於進一步的區分 undefined 和 null。
Boolean 類型的值有兩個,分別是 true 和 false,這兩個值和數字值不是一回事,也就是說 true 不必定等於 1,false 不必定等於 0,還有一點值得注意的是文章一開始就強調的一個概念,在 ECMAScript 中全部的一切都是區分大小寫的,因此 True 和 False (以及其餘混合大小寫的形式)並非 Boolean 類型的兩個值,只是標識符。如下是爲變量賦 Boolean 類型值的例子:
var found = true; var lost = false;
儘管 Boolean 類型的值只有兩個,可是在 ECMAScript 中,全部類型的值都有與這兩個 Boolean 值等價的值,將任意一種類型的值轉換爲對應的 Boolean 值,能夠調用轉型函數 Boolean(),例如:
var message = "Hello World!"; var messageAsBoolean = Boolean(message);
上面這個例子中,message 字符串被轉換成了 Boolean 值,轉換後的 Boolean 值被儲存在變量 messageAsBoolean 中。能夠對任何數據類型的值調用 Boolean() 函數,並且總會返回一個 Boolean 值。至於具體返回是 true 仍是 false 則要要具體的狀況而定,下面給出了轉換的規則:
數據類型 | 轉換爲true的值 | 轉換爲false的值 |
---|---|---|
Boolean | ture | false |
String | 任何非空字符串 | ""(空字符串) |
Number | 任何非零數字值(包括無窮大) | 0和NaN(參見本章後面有關NaN的內容) |
Object | 任何對象 | null |
Undefined | n/a① | undefined |
Number 類型應該算是幾種基本數據類型中比較複雜的類型吧。
在 Number 類型中,最簡單的應該算是十進制整數吧,十進制整數能夠直接像下面這樣在代碼中輸入:
var intNum = 9; // 整數 9
除了十進制之外,整數還能夠用二進制、八進制和十六進制來表示。
其中八進制必須以 0 開頭,而後是八進制數字序列(0-7),若是字面中的值超出了範圍,則第一個 0 將被忽略,後面的數值將被當成十進制數值解析。
var num1 = 070; // 八進制 56 var num2 = 079 // 無效的八進制數,被解析成十進制數 79 var num3 = 08; // 無效的八進制數,被解析成十進制數 8
八進制字面量在嚴格模式下是無效的,會致使支持的 JavaScript 引擎拋出錯誤。
十六進制必須以 0x 開頭,而後是十六進制數字序列(0-9 及 A-F),其中字母能夠大寫也能夠小寫,例如:
var num1 = 0xA; // 十六進制的 10 var num2 = 0x1f; // 十六進制的 31
在進行算數計算時,全部的八進制和十六進制表示的數值最終都將被轉換成十進制數值。
浮點數值必須包含一個小數點,且小數點後面必需要有一位**非 0 **數字纔算是浮點數值,若是小數點後沒有數字,則 ECMAScript 會自動忽略這個小數點,小數點前面則不必定要有數字,但不推薦這種寫法:
var num1 = 1.1; var num2 = 0.1; var num3 = .1; // 有效但不推薦 var num4 = 1.; // 小數點後面沒有數字,被解析爲 1 var num5 = 1.0; // 被解析成整數 1
因爲浮點數值所需的內存是整數數值所須要的內存的兩倍,因此 ECMAScript 會不失時機的將浮點數值轉化爲整數。
還有一點須要注意的是,浮點數值的最高精度是 17 位小數,在進行算術計算的時候其精度遠遠不如整數數值。好比,0.1 加上 0.2 的結果並非 0.3,而是 0.30000000000000004。這個小小的舍入偏差會致使沒法測試特定的浮點數值,例如:
var a = 0.1; var b = 0.2; if (a + b = 0.3) { // 不要這麼測試 alert("You got 0.3."); }
因爲內存的限制,ECMAScript 並不能保存全部的數值,ECMAScript 可以表示的最小數值保存在 Number.MIN_VALUE 中,可以表示的最大數值保存在 Number.MAX_VALUE 中,具體的來講,若是一個數值超出了 ECMAScript 所能保存的數值範圍,而且若是這個值是負數,則會被轉換成 -Infinity(負無窮),若是這個值是正數,則會被轉換成 +Infinity(正無窮)。
若是一個數被轉換成了無窮大(Infinity),則不能進行下一次運算,由於 Infinity 是不能被運算的數值。要想肯定一個數值是否是有窮的(是否是最大值和最小值之間),可使用 isFinite() 函數來肯定,若是處於最大值和最小值之間,則會返回 true,例如:
var result = Number.MAX_VALUE + Number.MAX_VALUE; var min = Number.MIN_VALUE; var max = Number.MAX_VALUE; alert(isFinite(result)); // false alert(isFinite(min)); // true alert(isFinite(max)); // true
由上可知,最大值和最小值也算是有窮的。
NaN 即非數值(Not a Number)是一個特殊的數值,NaN 是用來表示原本應該返回一個數值卻沒有返回數值的狀況(這樣就不會拋出異常了),例如在 ECMAScript 中,0 除以 0 並不會報錯,而是會返回 NaN,所以不會影響其餘代碼的執行。在這裏有一點須要注意的是,並非任意數值除以 0 都會返回 NaN 的,例如:
alert(0 / 0); // "NaN" alert(1 / 0); // "Infinity" alert(-1 / 0); // "-Infinity" alert(NaN / NaN); //"NaN"
由上可知,當正數除以 0 的時候,返回的是 Infinity,當負數除以 0 的時候,返回的是 -Infinity,只有 NaN 或者 0 初除以 0 的時候返回的纔是 NaN。
NaN 有兩個特色,首先,任何涉及 NaN 的操做都會返回 NaN;其次,NaN 與任何值都不相等,包括 NaN 自己。例以下面代碼會返回 false:
alert(NaN = NaN); // false
爲了判斷某個數值是不是「非數值」,ECMAScript 定義了 isNaN() 函數,該函數接受一個任意類型的參數,若是這個參數是 NaN,則返回 true,若是不是 NaN,則返回 false,例如:
alert(isNaN(NaN)); // true alert(isNaN(10)); // false(10 是一個數值) alert(isNaN("10")); // false(能夠被轉換成數值 10) alert(isNaN("blue")); // true(不能轉換成數值) alert(isNaN(true)); // false(能夠被轉換成數值 1)
由上可知,若是一個參數不能被轉換成數值,則 isNaN() 函數會返回 true。
值得一提的是,isNaN() 函數一樣適用於對象,在對對象調用 isNaN() 時,會首先調用對象的 valueOf() 方法試圖把對象轉換爲數值,若是不能轉換爲數值,則基於這個對象再調用 toString() 方法,在測試返回的值。
能夠把非數值轉換成數值的函數有 3 個,分別是 Number()、 parseInt() 和 parseFloat()。其中 Number() 適用於任何數據類型,另外兩個則專門用於把字符串轉換成數值。
Number() 函數的轉換規則以下:
若是是 Boolean 值,true 和 false 將分別被轉換爲 1 和 0。
若是是數字值,只是簡單的傳入和返回。
若是是 null 值,返回 0。
若是是 undefined,返回 NaN。
若是是字符串,遵循下列規則:
若是字符串中只包含數字(包括前面帶正號或負號的狀況),則將其轉換爲十進制數值,即"1"會變成 1,"123"會變成 123,而"011"會變成 11(注意:前導的零被忽略了);
若是字符串中包含有效的浮點格式,如"1.1",則將其轉換爲對應的浮點數值(一樣,也會忽略前導零);
若是字符串中包含有效的十六進制格式,例如"0xf",則將其轉換爲相同大小的十進制整數值;
若是字符串是空的(不包含任何字符),則將其轉換爲 0;
若是字符串中包含除上述格式以外的字符,則將其轉換爲 NaN。
若是是對象,則調用對象的 valueOf()方法,而後依照前面的規則轉換返回的值。若是轉換的結果是 NaN,則調用對象的 toString() 方法,而後再次依照前面的規則轉換返回的字符串值。
下面則是一些具體的例子:
var num1 = Number("Hello world!"); //NaN var num2 = Number(""); //0 var num3 = Number("000011"); //11 var num4 = Number(true); //1
parseInt() 的轉換規則以下:
var num1 = parseInt("1234blue"); // 1234 var num2 = parseInt(""); // NaN var num3 = parseInt("0xA"); // 10(十六進制數) var num4 = parseInt(22.5); // 22 var num5 = parseInt("070"); // 56(八進制數) var num6 = parseInt("70"); // 70(十進制數) var num7 = parseInt("0xf"); // 15(十六進制數)
parseInt() 在轉換字符串的時候會忽略字符串前面的空格,直到找到第一個非空格字符,若是第一個字符不是數字字符或者負號,parseInt() 就會返回 NaN;若是第一個字符是數字字符,parseInt() 會繼續解析第二個字符,知道解析完全部後足字符或遇到了一個非數字字符。有一點應該注意的是 parseInt() 轉換空字符串時會返回一個 NaN,而 Number() 轉換一個空字符串則會返回數字 0。
parseInt() 默認解析的是十進制數,但也能夠解析指定的進制,例如:
var num1 = parseInt("10", 2); //2 (按二進制解析) var num2 = parseInt("10", 8); //8 (按八進制解析) var num3 = parseInt("10", 10); //10 (按十進制解析) var num4 = parseInt("10", 16); //16 (按十六進制解析)
parseInt() 能夠接受第二個參數,第二個參數只能是 二、 八、 10 和 16,分別對應相應的進制。爲了不錯誤,當咱們用 parseInt() 轉換數值時指定相應的進制是很是有必要的。
parseFloat() 的轉換規則以下:
var num3 = parseFloat("22.5"); //22.5 var num4 = parseFloat("22.34.5"); //22.34 var num5 = parseFloat("0908.5"); //908.5 var num6 = parseFloat("3.125e7"); //31250000
與 parseInt() 相似,parseFloat() 也是從第一個字符開始解析每一個字符,一直解析到字符串的末尾,或者解析到一個無效浮點數字字符爲止。與 parseInt() 不一樣的是,parseFloat() 解析到的第一個小數點是有效的,而第二個小數點則無效,所以它後面的字符串也將被忽略。與 parseInt() 第二個不一樣的是 parseFloat() 會始終忽略第一個 0。
還有一點須要注意的是,若是字符串包含的是一個可解析爲整數的數(沒有小數點,或者小數點後都是零),parseFloat() 會返回整數:
var num1 = parseFloat("1234blue"); //1234 (整數) var num2 = parseFloat("1234.000"); //1234 (整數)
parseFloat() 只解析十進制數,因此它不接受第二個參數,這也是爲何 parseFloat() 始終會把十六進制的數值轉換成 0 的緣由:
var num2 = parseFloat("0xA"); // 0
String 類型表示字符串,能夠由雙引號("")或單引號('')表示,因此下面這兩種字符串都是有效的:
var firstName = "Clear"; var lastName = 'Design';
但有一點須要注意的是,以什麼引號開頭就必須以什麼引號結尾,好比下面這種寫法就是錯誤的:
var name = "Clear Design';
String 數據類型包含一些特殊的字符字面量,也叫轉義序列,以下:
字面量 | 含義 |
---|---|
\n | 換行 |
\t | 製表 |
\b | 空格 |
\r | 回車 |
\f | 進紙 |
\\ | 斜槓 |
\' | 單引號('),在用單引號表示的字符串中使用。例如:'He said, \'hey.\'' |
\" | 雙引號("),在用雙引號表示的字符串中使用。例如:"He said, \"hey.\"" |
\xnn | 以十六進制代碼nn表示的一個字符(其中n爲0~F)。例如,\x41表示"A" |
\unnnn | 以十六進制代碼nnnn表示的一個Unicode字符(其中n爲0~F)。例如,\u03a3表示希臘字符Σ |
ECMAScript 中的字符串是不可變的,字符串一旦建立,它們的值就不能改變。要改變某個變量保存的字符串,首先要銷燬原來的字符串,而後再用另外一個包含新值的字符串填充該變量,例如:
var lang = "Java"; lang = lang + "Script";
上面的 lang 開始時包含 "Java",而第二行代碼把 lang 從新定義爲 "Java" 和 "Script" 的組合,即 "JavaScript"。第二行代碼並非把原來的 lang 的值改變了,而是首先建立一個能容納 10 個字符的新字符串,而後在這個字符串中填充 "Java" 和 "Script",因爲新的字符串拼接完成後,原來的字符串已經沒有用了,因此原來的字符串 "Java" 和 "Script" 會被銷燬,這些都是發生在後臺的。
前面提到 Number 數據類型的時候有提到 parseInt() 和 parseFloat() 兩個函數,這兩個函數的做用是將可轉換成數值的字符串轉換成數值,而 String 數據類型一樣也提供了一個 toString() 函數,它的做用是把可轉換爲字符串的數據類型轉換成字符串:
var age = 22; var ageAsString = age.toString(); // "22" var found = true; var foundAsString = found.toString(); // "true"
Number、 Boolean、 Object 和 String(沒錯,String 自己也具備 toString() 方法,該方法返回該字符串的一個副本)都有 toString() 方法,但 Null 和 Undefined 沒有這個方法。
toString() 方法接受一個參數,參數只能是 二、 八、 10 和 16,分別對應相應的進制。例如:
var num = 10; alert(num.toString()); // "10" alert(num.toString(2)); // "1010" alert(num.toString(8)); // "12" alert(num.toString(10)); // "10" alert(num.toString(16)); // "a"
默認狀況(沒有傳入參數)下 toString() 方法以十進制格式返回數值的字符串表示。在不知道傳入的值是否是 Null 或 Undefined 的時候,可使用 String() 轉型函數,該函數支持把任意數據類型的值轉換爲字符串,String() 函數的轉換規則以下:
下面再看幾個例子:
var value1 = 10; var value2 = true; var value3 = null; var value4; alert(String(value1)); // "10" alert(String(value2)); // "true" alert(String(value3)); // "null" alert(String(value4)); // "undefined"
Object 類型是 ECMAScript 中 6 種數據類型中惟一一種複雜數據類型,簡單的說的話 ECMAScript 中對象就是一組數據和功能的集合。建立對象的方法有不少,這裏說一下比較經常使用的一種方法,就是經過執行 new 操做符後跟要建立的對象類型的名稱來建立:
var o = new Object();
在瞭解對象以前,首先要先理解一個重要的思想:在 ECMAScript 中,Object 類型是全部它的實例的基礎。也就是說,Object 類型所具備的任何屬性和方法也一樣存在於更具體的對象中。
Object 的每一個實例都具備下列屬性和方法:
constructor:保存着用於建立當前對象的函數。對於前面的例子而言,構造函數(constructor)就是 Object()。
hasOwnProperty(propertyName):用於檢查給定的屬性在當前對象實例中(而不是在實例的原型中)是否存在。其中,做爲參數的屬性名(propertyName)必須以字符串形式指定(例如:o.hasOwnProperty("name"))。
isPrototypeOf(object):用於檢查傳入的對象是不是傳入對象的原型(第 5 章將討論原型)。
propertyIsEnumerable(propertyName):用於檢查給定的屬性是否可以使用 for-in 語句
(本章後面將會討論)來枚舉。與 hasOwnProperty() 方法同樣,做爲參數的屬性名必須以字符串形式指定。
toLocaleString():返回對象的字符串表示,該字符串與執行環境的地區對應。
toString():返回對象的字符串表示。
valueOf():返回對象的字符串、數值或布爾值表示。一般與 toString() 方法的返回值相同。
在 ECMAScript 中,Object 是全部對象的基礎,也是 ECMAScript 中須要掌握的重點,因此筆者將在後面的學習筆記中詳細地對 Object 進行總結,這裏就先了解一些 Object 類型的基本概念的方法。
以上部分主要是筆者對 ECMAScript 中的一些基本概念的簡單總結,本篇主要寫的仍是在進一步學習 ECMAScript 中須要瞭解的一些基本且重要的概念。
若有寫的很差的地方還請多指出討論。