JavaScript型別可分為兩大類:
這次我們來討論物件型別(Object Type)。
建立物件最簡單且直覺的方式,是使用物件字面值的方式建立:
let car = {
make: 'toyota',
model: 'camry',
year: 2018,
color: 'red'
}
首先宣告變數,代表這個物件的名稱,在指定運算式的右邊,使用大括號{ }建立物件的本體,加入每個屬性名稱與值(屬性名稱:值),每對屬性/值之間,使用逗號分隔。
以上就完成最簡單的物件建立。
剛剛建立了car物件,有4個屬性,分別是make、model、year、color,以及這些描述這些屬性的值。
要取得屬性值,可以使用.(dot)或中括號[ ]運算子。
console.log(car.make); //toyota
console.log(car['model']); //camry
我們也可以設定方法,讓此物件具有邏輯處理的能力。
let car = {
make: 'toyota',
model: 'camry',
year: 2018,
color: 'red',
run: function () {
console.log(`${this.model} is running`);
}
}
car.run(); //camry is running
this關鍵字,指的是car這個物件。
物件的結構看似複雜,其實只要掌握一個原則:物件裡面只有屬性跟方法。
物件.屬性
物件.方法
基本型別(Primitive Type)與物件型別(Object Type)有個很大的差異就是基型值是不可變(immutable)的,而物件是可變的,這究竟是什麼意思?
所謂的不可變(immutable)意指,當我們在操作基型值所回傳的結果,看似已經修改後結果,但實際上是回傳一個新的值,舉例來說:
let str = 'hello';
console.log(str.toUpperCase());
console.log(str);
結果
toUpperCase( )的結果回傳大寫,但實際上並未改變str原本的內容。
let obj1 = {
prop: 'obj1'
}
let obj2 = obj1;
obj2.prop = 'obj2';
console.log(obj1.prop); //obj2
console.log(obj2.prop); //obj2
物件的操作是透過參考(by reference),而非值(by value),obj2與obj1參考到的其實是同一個物件,當改變obj2所參考到的物件屬性值,相對的,也會改變obj1的物件屬性值。
物件之間可以合併,也很常使用到,我們可以使用assign方法來實現:
let car1 = {
make: 'toyota',
model: 'camry',
year: 2018,
color: 'red'
}
let car2 = {
make: 'toyota',
model: 'rav4',
year: 2018,
color: 'white',
type: 'suv',
run: function () {
console.log(`${this.model} is running`);
}
}
Object.assign(car1, car2);
console.log(car1);
結果
car2會合併到car1,有幾點要注意:
若不想覆蓋原本的物件,可以在參數中設空物件,並傳給新的物件:
let car3 = Object.assign({}, car1, car2);
console.log(car3);
console.log(car1);
結果
我們除了可以自己建立物件,來達到客製的需求之外,在開發Web的過程當中,往往需要更多關於瀏覽器或JavaScript的資訊,內建物件能提供一般程式開發常會使用到的功能,無需我們另外撰寫,當Web應用程式開始執行的時候,這些內建物件會一同被載入使用。
內建物件可分為三大類:
瀏覽器物件
也就是window物件,它代表目前的瀏覽器視窗或頁籤,window物件的屬性與函式非常多。
DOM
文件物件模型(Document Object Model),它代表當前網頁的頁面。
當瀏覽器解析網頁時,會將HTML轉成DOM,放入記憶體中,JavaScript藉由控制DOM,來操縱網頁的行為。
JavaScript全域物件
基本功能物件,包括Array、Date、String、Number、Error等,讓我們在程式設計的過程當中可針對特定型別的物件做處理,它的功能相當多,我會在其他篇幅一一介紹。
我們建立一個物件,並設定屬性值:
let obj = {
prop: 'Hello'
}
console.log(obj.prop); //Hello
當我們需要取得屬性值,可以使用obj.prop,一切看起來很合理。
String也可以使用類似的方式取得長度:
let str = 'Hello world';
console.log(str.length); //11
可是明明String不是Object,沒有屬性,為何它可以用這種方式取得資料?
因為當我們需要參考到Primitive的資訊時,JavaScript會自動把Primitive轉型成Object,這時它就可以當成物件來處理,一旦執行完畢,這臨時新建的物件,生命週期也隨之結束。
這種物件也就稱為包裹(Wrapper)物件,就好像在Primitive Type身上包了物件的外衣一樣,讓Primitive Type短暫地擁有物件的行為。
這種物件跟一般物件的差異在於,它們的屬性都是唯讀的,我們不能改變也無法定義新屬性,這非常容易理解,因為我們只是要知道Primitive Type的資訊,如果藉由包裹(Wrapper)物件的方式去改變原本的屬性值,是很不合理的。
參考來源:
JavaScript大全
Speaking JavaScript|簡明完整的 JS 精要指南