JavaScript淺嚐紀錄No.5-呈現真實世界的物件該如何運用?
物件(Object)
MDN中如此介紹:
物件是一批相關的數據以及/或者功能,可裝載相關的資料與程式碼,資料部分是你塑造某個模型的資訊,而程式碼部分則用是操作行為(Method)實現。Object data – 函式部分通常也使用 —可工整地儲存 (正式一點應該是封裝 Encapsulated) 在物件包裹(這個包裹有特定的稱呼方式,有時候即所謂的命名空間 Namespace) ,使其能輕鬆地建構性存取。物件也常作為「資料儲存 (Datastore),促成簡易實現跨網傳送。。
物件表示法
在物件中,屬性代表靜態的資料,用於描述物件的狀態;**方法(函式)**代表物件的功能,或說物件的行為。
物件實字
利用
{}
創建物件。1
2
3
4
5
6
7
8
9
10let person = {} //空物件
let person = {
name: 'Bob',
age: 32,
gender: 'male',
interests: ['music', 'skiing'],
greeting: function () {
console.log('Hi! I\'m ' + this.name[0] + '.');
}
} //直接在{}中寫下key-value pair的值可以透過**點記法(Dot notation)或是括弧記法(Bracket notation)**存取物件的屬性與函式。
以上面的
person
物件來當例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22//點記法
//括弧記法,記得使用['key']取值時,key一定要加''
console.log(person.name) //取得姓名值 "Bob"
console.log(person['name']) //取得姓名值 "Bob"
person.age = 45 //更改年齡值為 45
person['age'] = 45 //更改年齡值為 45
console.log(person.name) //取得年齡值 45
console.log(person['age']) //取得年齡值 45
//物件中包含物件,如何取值
let person = {
name: {
first: 'Bob',
last: 'Smith'
},
}
console.log(person.name.last) //取得姓名last值'Smith'
console.log(person['name']['last']) //取得姓名last值'Smith'
person.name.first = 'Cratchit' //更改姓名first值'Cratchit'
person['name']['first'] = 'Cratchit'//更改姓名first值'Cratchit'
console.log(person.name.first) //取得姓名first值'Cratchit'
console.log(person['name']['first']) //取得姓名first值'Cratchit'
建構函式(constructor function)
高效率的建構擁有相同屬性或方法的物件,即是用多個物件類別建置相同功能,並且使用`new`關鍵字來呼叫建構函式。
建構函式名稱往往以大寫字母起頭,如此可方便在程式碼中找出建構函式。
寫法如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//利用function創建物件基本架構
function ConstructorName(parameter) {
this.propertyName = value;//可以帶入參數
this.methodName= function() {
console.log('Hi! I\'m ' + this.name + '.');
};
}
//範例
function Person(name) {
this.name = name;
this.greeting = function() {
console.log('Hi! I\'m ' + this.name + '.');
};
}
在上面程式碼中的this
代表著物件擁有者,誰使用了這個建構函式,那麼這個this
就指向他。
看一下下面的程式碼,先利用關鍵字new
及建構函式來創建新的物件,就能明白this
指向誰了。
1 | let Bob = new Person('Bob') |
點記法(Dot notation)v.s括弧記法(Bracket notation)
- 括弧記法可以利用變數作為屬姓名取值,點記法不行,並且會出現
undefined
。
1 | let obj = {} |
- 括弧記法可以利用數字做為屬姓名,點記法不行,會出現
Uncaught SyntaxError: Unexpected numbe
。
1 | let obj = {} |
- 括弧記法可以動態(如加減)的設定變數名,點記法不行,會出現
Uncaught SyntaxError: Unexpected template string
。
1 | let obj = {} |
物件方法應用
Object.assign() 複製物件
寫法Object.assign(target, ...sources)
,target
需要複製的物件,sources
複製的來源(被複製的物件)。
基本款
1
2
3
4
5
6
7
8
9const obj = {
a: 1,
b: 2,
c: 3
}
const copyObj = Object.assign({}, obj) //把obj複製給空物件{}
console.log(obj) //{a: 1, b: 2, c: 3}
console.log(copyObj)//{a: 1, b: 2, c: 3}
console.log(obj===copyObj)//false複雜款
複製來源(
sources
)有許多個,並且source
裡有相同的key值,那麼複製時,後面來源會將前面來源的value值覆蓋掉。1
2
3
4
5
6
7
8
9
10
11
12
13const obj1 = {
a: 1,
b: 2,
c: 3
}
const obj2 = {
b: 4,
c: 5
}
const copyObj = Object.assign({}, obj1, obj2) //將obj1, obj2複製給空物件{}
console.log(obj1) //{a: 1, b: 2, c: 3}
console.log(obj2) //{b: 4, c: 5}
console.log(copyObj) //{a: 1, b: 4, c: 5} 複製時obj2會將obj1中相同key的value值覆蓋掉,所以b跟c會是obj2的值複製來源(
sources
)物件值是物件包裹子物件的話,Object.assign()
只會複製該子物件的參照位址,如果要讓相同內容的物件(有子物件)有新的參照位址可以參考JSON.parse(JSON.stringify())
的作法。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16let a = {
b: {
c: 4
},
d: {
e: {
f: 1
}
}
}
let g = Object.assign({}, a) // 淺層複製
let h = JSON.parse(JSON.stringify(a)); // 深層複製
console.log(a=== g) //false,a、g指向不同參照位址,但裡面的子物件指向相同的位址。
console.log(a=== h)//false,a、h(及裡面的子物件)指向不同參照位址。
console.log(g.d.e === a.d.e) // true,淺層複製,b、d、e都是複製參照位址所以值為相同。
console.log(h.d.e === a.d.e) // false,深層複製,b、d、e指向不同的參照位址。複製的target會被sources影響。
1
2
3
4
5
6
7
8
9
10
11
12
13const obj1 = {
a: 1,
b: 2,
c: 3
}
const obj2 = {
b: 4,
c: 5
}
const copyObj = Object.assign(obj1, obj2)//這時的obj1與copyObj是相同的
console.log(obj1) //{a:1,b:4,c:5}
console.log(copyObj) //{a:1,b:4,c:5}
console.log(obj1===copyObj) //true
參考資料:
MDN-JavaScript 物件基礎概念
MDN-初學者應知道的物件導向 JavaScript
JavaScript中物件屬性通過點(.)和方括號([])取值的不同之處
w3school-JavaScript this 关键词
MDN-Object