前導知識 1. 大多數開發者在使用Java或C 等基於類的語言的過程中學會了面向對象編程。由於JavaScript沒有對類的正式支持,這些開發者在學習JavaScript時往往會迷失方向; 2. JavaScript不需要在開頭就定義好各種類,你可以在寫代碼的過程中根據需要創建數據結構 ; 3. 由 ...
概述
大多數開發者在使用Java或C#等基於類的語言的過程中學會了面向對象編程。由於JavaScript沒有對類的正式支持,這些開發者在學習JavaScript時往往會迷失方向;
JavaScript不需要在開頭就定義好各種類,你可以在寫代碼的過程中根據需要創建數據結;
由於JavaScript缺少類,也就缺少用於對類進行分組的包;
JavaScript把對象作為語言的中心,幾乎所有JavaScript的數據要麼是一個對象要麼從對象中獲取;
在JavaScript中也被視為對象,這使得它們成為JavaScript的一等公民;
用和理解對象是理解整個Javascript的關鍵,在學習之前,首先要學習鑒別和使用兩種JavaScript基本數據類型:原始類型和引用類型。
什麼是類型
JavaScript雖然沒有類的概念,但依然存在兩種類型:原始類型和引用類型;
原始類型保存為簡單數據值;
引用類型保存為對象,其本質是指向記憶體位置的引用;
其他編程語言使用棧存儲原始類型,用堆存儲引用類型,JavaScript完全不同:它使用一個變數對象追蹤變數的生存期;
原始值被直接保存在變數對象內,引用值則作為一個指針保存在變數對象內,該指針指向實際對象在記憶體中的存儲位置。
原始類型
JavaScript共有5種原始類型:
boolean
布爾,值為true或falsenumber
數字,值為任何整型或浮點數值
string
字元串,值為單引號或雙引號括出的單個字元或連續字元null
空類型undefined
未定義JavaScript和許多其他語言一樣,原始類型的變數直接保存原始值。當你將原始值賦給一個變數時,該值將複製到變數中。也就是說,如果你使一個變數等於另一個時,每個變數有它自己的一份數據拷貝。
var c1 = "red"; var c2 = c1;
每個含有原始值的變數使用自己的存儲空間,一個變數的改變不會影響到其他變數。
var c1 = "red"; var c2 = c1; console.log(c1); //"red" console.log(c2); //"red" c1 = "blue"; console.log(c1); //"blue" console.log(c2); //"red"
鑒別原始類型
鑒別原始類型的最佳方法是使用typeof操作符。
console.log(typeof "Hello"); //"string" console.log(typeof 100); //"number" console.log(typeof 10.5); //"number" console.log(typeof true); //"boolean" console.log(typeof undefined); //"undefined" console.log(typeof null) //"object"
當運行
typeof null
時,結果是object。這實際上是一個錯誤,判斷一個值是否為空類型的最佳方法是直接和null比較。console.log(value === null); //true or false
原始方法
- 雖然string,number,boolean是原始類型,但是它們也擁有方法;
- 儘管原始類型擁有方法,但它們不是對象;
- JavaScript使它們看上去像對象一樣,以此來提供語言上的一致性體驗。
var name = "Tom"; var firsetLetter = name.chrAt(0); //get first character var lowercaseName = name.toLowerCase(); //convert to lowercase
引用類型
- 引用類型是指JavaScript中的對象,同時也是在JavaScript中能找到的最接近類的東西;
- 引用值是引用類型的實例,也是對象的同義詞;
- 對象是屬性的無序列表;
- 屬性包含鍵和值;
- 如果一個屬性的值是函數,它就被稱為方法;
- 在使用對象前,必須先創建他們。
創建對象
JavaScript有好幾種方式可以創建對象,或者說實例化對象;
第一種是使用
new
操作符和構造函數;構造函數是通過
new
操作符來創建對象的函數,一般首字母大寫,下列代碼實例化一個通用對象;var object = new Object(); //實例化一個通用對象
引用類型不在變數中直接保存對象,所以上面例子中object變數實際上並不包含對象的實例,而是一個指向記憶體中實際對象所在位置的指針(或者說引用);
當將一個對象賦值給變數時,實際是賦值給這個變數一個指針。這意味著,將一個變數賦值給另一個變數時,兩個變數各獲得了一份指針的拷貝,指向記憶體中的同一個對象。
對象引用解除
不使用對象時將其引用解除,讓垃圾收集器對那塊記憶體進行釋放。解除引用的最佳手段是將對象變數置為null。
var obj = new Object(); obj = null; // 解除引用
添加刪除屬性
在JavaScript中,可以在對象中隨時添加和刪除其屬性。
var obj1 = new Object(); var obj2 = obj1; obj1.myProperty = "aaa"; console.log(obj2.myProperty); //"aaa"
上面的例子演示了JavaScript一個獨特的方面:可以隨時修改對象,即使並沒有在開始時定義它們。同時,後續會講到如何阻止此類修改。
內建類型實例化
我們已經見過如何用
new Object()
創建和使用通用對象。Object類型只是JavaScript提供的少量內建類型之一。其他內建類型各有它們的特殊用途,可在任何時候被實例化。
Array
數組類型,以數字為索引的一組值的有序列表
Date
日期和時間類型Error
運行期錯誤類型Function
函數類型Object
通用對象類型RegExp
正則表達式類型可以用
new
來實例化每一個內建引用類型。字面形式
內建引用類型有字面形式。字面形式允許你在不需要使用
new
操作符和構造函數顯式創建對象的情況下生成引用值(言外之意就是:除了使用new
構造函數創建對象還有一種字面形式的方式創建對象)。對象和數組字面形式
要用對象字面形式創建對象,可以在大括弧內定義一個新對象及其屬性;
屬性的組成包括一個標識符或字元串、一個冒號及一個值;
多個屬性之間用逗號分隔;
var book = { name:"JavaScript教程", year:"2019", price:34.5 }
- 屬性名字也可以用字元串表示,特別是當你希望名字中包含空格或其他特殊字元時;
var book = { "name":"JavaScript教程", "year":"2019", "price":34.5 }
上面兩個例子的等價寫法
var book = new Object(); book.name = "JavaScript教程"; book.year = "2019"; book.price = 34.5;
- 定義數組的字面形式是在中括弧內用逗號區分任意數量的值。
var colors = ['red', 'blue', 'green']; console.log(colors[0]); //'red'
等價於
var colors = new Array('red', 'blue', 'green'); console.log(colors[0]);
函數字面形式
通常都要用函數的字面量來定義函數;
考慮到可維護性、易讀性和調試上的巨大挑戰,通常不會有人使用函數的構造函數。
function fun(value) { return value; } //is same as var fun = new Function("value", "return value;");
訪問屬性
屬性是對象中保存的名字和值的配對;
.
是JavaScript中訪問屬性的最通用做法;var arr = []; arr.push(1000);
也可以使用中括弧訪問JavaScript屬性。
var arr = []; arr["push"](1000);
鑒別引用類型
函數使用
typeof
操作符時,返回值是function
;非函數的引用
typeof
操作符時,返回值是object
;為了更方便的鑒別引用類型,使用
instanceof
操作符;
對象的引用 instanceof 構造函數
對象是構造函數所指定的類型的一個實例,
instanceof
返回true
;否則返回
false
。var items = []; var object = {}; function fun(val) { return val; } console.log(items instanceof Array); //true console.log(object instanceof Object); //true console.log(fun instanceof Function); //true
instanceof
操作符可鑒別繼承類型,這意味著所有對象都是Object的實例,因為所有引用類型都繼承自Object。var items = []; var object = {}; function fun(val) { return val; } console.log(items instanceof Object); //true console.log(object instanceof Object); //true console.log(fun instanceof Object); //true
每種引用類型的對象都被正確鑒別為Object的實例。
鑒別數組
除了
instanceof
可以鑒別數組,ECMAScript5引入了Array.isArray()
來明確鑒別一個值是否為Array的實例。
原始封裝類型
- 原始封裝類型共有3種(
String
、Number
、Boolean
),這三種是引用類型;- 這些引用類型使得原始類型用起來和對象一樣方便(類似於Java中的包裝類);
- 當讀取字元串、數字或布爾值時,原始封裝類型將被自動創建;
var name = "Tom"; var firstChar = name.charAt(0); console.log(firstChar);
等價於
var name = "Tom"; var temp = new String(name); var firstChar = temp.charAt(0); temp = null; console.log(firstChar);
- 手動創建的原始封裝類型在其他地方很容易讓人誤解,在大多數情況下都只會導致錯誤。多數情況下,應避免使用原始封裝類型。