物件是一批相關的數據以及/或者功能(通常包含了幾個變數及函式 — 當它們包含在物件中時被稱做「屬性」(properties)或「函式」(methods))。
物件結構
物件宣告方式有兩種
- 物件實字(Object Literals)
宣告一個物件名稱,並於賦值運算子後方填入{}
作為區塊宣告。
- 物件本身的組成是由一個 {屬性(property) : 值(value)} 組成的,屬性的值可以是任何合法的值,可以包含陣列、函式或其他物件。
- 如果是一般的值的情況,稱為"屬性(property, prop)",如果是一個函式,稱之為"方法(method)"。屬性與方法我們通常合稱為物件中的成員(member)。
- 物件中的每一個成員(member)須以
,
相隔。 - 屬性定義上一律為字串,固可使用特殊字元。
var object = { properties: value, array: [], object: {}, holloworld: function() { console.log('Hello World') } }
|
屬性名稱(鍵)中也不要使用保留字,請使用合法的變數名稱
2. 建構式方式
通常用於建構新物件中的屬性。
多數情況請使用物件實字(Object Literals)宣告物件
參考:
從ES6開始的JavaScript學習生活-物件
物件取值、新增、刪除
物件取值取值、新增、刪除有以下兩種,分別為
- 點記法 (Dot notation)
可透過點記法 (Dot notation) 存取物件的屬性與函式。
物件名稱作為命名空間 (Namespace),接著寫一個"."以及想取值、新增、刪除的屬性 or 方法名稱。
點記法只可接受字串表示的成員名稱,不能是指向變數名稱。
- 取值
物件名稱.屬性名稱 物件名稱.子物件名稱.屬性名稱 物件名稱.方法名稱()
|
- 更新(新增)
透過賦值運算子將值賦予現有屬性與函式的數值,也可以建立全新的成員。物件名稱.屬性名稱 = 值 物件名稱.方法名稱 = function() {console.log('hello world')}
|
- 刪除
使用一元運算子delete
刪除現有屬性與函式的數值。
delete 物件名稱.屬性名稱 delete 物件名稱.方法名稱
|
- 括弧記法 (Bracket notation)
括弧記法 (Bracket notation) 是另一種存取物件屬性的方法。
將要存取屬性名稱使用"[]"包覆起來。
如屬性名稱為變數值可使用括弧記法。
- 取值
物件名稱['屬性名稱'] 物件名稱[變數名稱] 物件名稱[方法名稱]()
|
- 新增
透過賦值運算子將值賦予現有屬性與函式的數值,也可以建立全新的成員,與點記法相同。物件名稱['屬性名稱'] = 值 物件名稱[變數名稱] = 變數值 物件名稱['方法名稱']()
|
- 刪除
使用一元運算子delete
刪除現有屬性與函式的數值,與點記法相同。
delete 物件名稱['屬性名稱'] delete 物件名稱['方法名稱']
|
此方式與陣列取值方式相似,陣列取值使用指數 (index number) 選擇項目;而括弧記法 (Bracket notation)取值是透過各成員數值相關的名稱來選擇項目。
補充:
變數無法被刪除,屬性才能被刪除。
使用 var 宣告變數,此變數無法被刪除。
如直接使用賦值運算子賦予一個值,類似於全域變數下新增一個屬性window.property = value
。
var a = 1 aa = 1 delete a console.log(a) delete aa console.log(aa)
|
物件與純值
- 純值(Primitive Types)又稱為原始型別,可參考:。
var name = '小明' console.log(name) name.age = 30 console.log(name)
|
var newName = new String('小明') console.log(newName)); newName.age = 30; console.log(newName);
|
- 未定義的物件屬性預設值
物件下未定義屬性的值為undefined,並於undefined下無法新增任何屬性。
物件的參考特性
- 傳值(Call By Value):
把 值 傳到 另一個記憶體位置 的 值 上。
當宣告一個 primitive type 的變數時(如:數字、字串、布林),假設把 preson 指定成一個 primitive type 的時候,preson 會在記憶體中存在一個自己的位置(0x01)。當指定另一個變數 preson2 = preson
的時候,preson2 實際上會建立另一個獨立的記憶體位置(假設叫做0x02),接著再把 preson 的值存在這個獨立的記憶體位置。
preson 和 preson2 其實是存在於兩個不同的記憶體位置,因此彼此並不會乎相干擾影響,當修改preson2的值時,preson仍不會變。
在 JavaScript 中 primitive type(Boolean, String, Number, null, undefined)都屬於 Call By Value。
物件參考觀念-延伸範例
Call by Reference 還是 Call by Sharing
傳遞給函式的是它的實際參數的隱式參照而不是實參的拷貝。
與傳參照呼叫不同,對於呼叫者而言在被呼叫函數裡修改參數是沒有影響的。
參考:求值策略- 维基百科
淺層複製及深層複製
只能達到淺層的複製(第一層),若有第二層以上的資料的話,
就無法達到實際的複製,而是會與舊物件一起共用同一塊記憶體。
有下列3種方式
var family = { name: '小明家', members: { father: '老爸', mon: '老媽', ming: '小明' } }; var newFamily = {} for (var key in family) { newFamily[key] = family[key] } console.log(family === newFamily) console.log(newFamily) newFamily.name = "大明家" console.log(newFamily)
console.log(family.members === newFamily.members)
|
var newFamily2 = jQuery.extend({}, family)
|
var newFamily3 = Object.assign({}, family)
|
var newFamily4 = {...family}
|
會另外創造一個一模一樣的物件,新物件跟原物件不共用記憶體,修改新物件不會改到原物件。
- 轉成 JSON 再轉回來
用JSON.stringify
把物件轉成字串,再用JSON.parse
把字串轉成新的物件。
缺點:繼承的屬性會遺失。
var newFamily5 = JSON.parse(JSON.stringify(family)) console.log( family === newFamily5 ) console.log( family.members === newFamily5.members )
|
- Lodash
另外一個很熱門的JS函式庫 lodash,提供_.cloneDeep
用來做 Deep Copy。
lodash
API
var newFamily6 = _.cloneDeep(family); console.log( family === newFamily6 ) console.log( family.members === newFamily6.members )
|
陣列(Array)
陣列是一種有順序的複合式的資料結構,用於定義、存放複數的資料類型,陣列是用來把複數的值存進一個變數裡,可以是原始的資料類型、其他陣列、函式等等。
註: 雖然陣列資料類型是屬於物件,但Array這個包裝物件的 typeof Array
也是回傳’function’。
定義方式
- 一:
將複數的值以 ,
隔開並使用方括號 []
包覆存進一個變數內。
var newArray = [1, 'string', function(){console.log('hello world')}, true, {}]
|
- 建構式:
這種方式並不建議使用,使用此語法在分配後,會把長度值(成員個數)固定住,除非你百分之百確定陣列裡面的成員個數,不然千萬不要用。
var aArray = new Array(10) var bArray = new Array(1,2,3)
|
註: JavaScript的內建物件都不建議new作初始定義的。不過有一些特例是一定要的,例如Date、Error等等。
每一個陣列中的元素,都附有一個能讀相對應元素的數字,稱做數字索引(numeric index)。
是從0開始的順序整數值,可以用方括號 []
來取得成員的指定值,也可以用這個方式來改變成員包含的值。
console.log(newArray[0]) console.log(newArray[1]) console.log(newArray[2]()) console.log(newArray[3])
|
注意事項
- 多維陣列
多維陣列指的是"陣列中的陣列"結構,只是在陣列中保存其他的陣列值。
維數過多時在處理上會愈複雜,一般常見的只有二維。
var newArray = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
|
- 儲存多種資料類型
- 多洞的陣列(Holey Arrays)或稀疏陣列(Sparse Arrays)
在定義陣列時,它的陣列值和索引(index)並沒有塞滿,或是從一個完整的陣列刪除其中一個(留了個空位)。