對象
對象可以通過花括號 {…}
和其中包含一些可選的屬性來創建。屬性是一個鍵值對,鍵是一個字符串(也叫做屬性名),值可以是任何類型。
我們可以把對象想象成存放文件的櫥櫃。文件按照他們的名字來排列。這樣根據文件名我們就很容易找到、添加或刪除一個文件了。
我們可以用下面兩種語法的任一種來創建一個空的對象(“空櫃子”):
let user = new Object(); // “構造函數” 的語法
let user = {}; // “字面量” 的語法
通常,我們用花括號。這種方式我們叫做字面量。
文本和屬性
我們可以在創建的時候立即給對象一些屬性,在 {...}
裏面放置一些鍵值對。
let user = { // 一個對象
name: "John", // 鍵 "name",值 "John"
age: 30 // 鍵 "age",值 30
};
屬性有鍵(或者也可以叫做名字,標識符),在冒號的前面 ":"
,值在冒號的右邊。
在 user
對象中, 有兩個屬性:
- 第一個的鍵是
"name"
值是"John"
。 - 第二個的鍵是
"age"
值是30
。
是一個陳列着標記有兩個 “name” 和 “age” 簽名文件的櫥櫃。
任何時候我們都可以添加,刪除,讀取文件。
移除一個屬性,我們用 delete
操作:
delete user.age;
存在值檢查
有一個特別的操作符 "in"
來檢查是否屬性存在。
"key" in object
let user = { name: "John", age: 30 };
alert( "age" in user ); // true,user.age 存在
alert( "blabla" in user ); // false,user.blabla 不存在。
“for…in” 循環
爲了使用對象所有的屬性,就可以利用 for..in
循環。這跟 for(;;)
是完全不一樣的東西。
for(key in object) {
// 各個屬性鍵值的執行區
}
let user = {
name: "John",
age: 30,
isAdmin: true
};
for(let key in user) {
// keys
alert( key ); // name, age, isAdmin
// 屬性鍵的值
alert( user[key] ); // John, 30, true
}
複製和合並,Object.assign
如果我們真的想這麼做,就需要創建一個新的對象,遍歷現有對象的屬性,在原始值的狀態下複製給新的對象。
let user = {
name: "John",
age: 30
};
let clone = {}; // 新的空對象
// 複製所有的屬性值
for (let key in user) {
clone[key] = user[key];
}
// 現在複製是獨立的複製了
clone.name = "Pete"; // 改變它的值
alert( user.name ); // 原對象屬性值不變
我們也可以用Object.assign 來實現。
Object.assign(dest[, src1, src2, src3...])
//參數 dest 和 src1, ..., srcN(可以有很多個)是對象。
let user = { name: "John" };
let permissions1 = { canView: true };
let permissions2 = { canEdit: true };
// 把 permissions1 和 permissions2 的所有屬性都拷貝給 user
Object.assign(user, permissions1, permissions2);
// 現在 user = { name: "John", canView: true, canEdit: true }
let user = {
name: "John",
age: 30
};
let clone = Object.assign({}, user);
總結
對象是具有一些特殊特性的關聯數組。
他們存儲鍵值對:
- 屬性的鍵必須是字符串或者符號(通常是字符串)。
- 值可以是任何類型。
我們可以用下面的方法獲取屬性:
- 點符號:
obj.property
。 - 方括號
obj["property"]
,方括號中可以使用變量obj[varWithKey]
。
其他操作:
- 刪除屬性:
delete obj.prop
。 - 檢查屬性是否存在:
"key" in obj
。 - 遍歷對象:
for(let key in obj)
循環。
對象根據引用來賦值或者複製。換句話說,變量存的不是對象的"值",而是值的 “引用”(內存地址)。 所以複製變量或者傳遞變量到方法中只是複製了對象的引用。 所有的引用操作(像增加,刪除屬性)都作用於同一個對象。
深拷貝的話我們可以使用 Object.assign
或者 _.cloneDeep(obj)。
我們在這一章學習的叫做“基本對象” — 對象。
JavaScript 中還有很多其他類型的對象:
Array
存儲有序數據集合。Date
存儲時間日期。Error
存儲錯誤信息
構造函數和操作符 "new"
構造函數
構造函數在技術上是常規函數。不過有兩個約定:
- 他們首先用大寫字母命名。
- 它們只能用
"new"
操作符來執行。
function User(name) {
this.name = name;
this.isAdmin = false;
}
let user = new User("Jack");
alert(user.name); // Jack
alert(user.isAdmin); // false
構造函數 Return
有 return
語句,那麼規則很簡單:
- 如果
return
對象,則返回它,而不是this
。 - 如果
return
一個原函數,則忽略。
function BigUser() {
this.name = "John";
return { name: "Godzilla" }; // <-- returns 一個 object
}
alert( new BigUser().name ); // 哇哦,得到了對象,name 屬性值爲 Godzilla ^^
function SmallUser() {
this.name = "John";
return; // 完成執行,returns this
// ...
}
alert( new SmallUser().name ); // John
總結
- 構造函數或簡言之,就是常規函數,但構造函數有個共同的約定,命名它們首字母要大寫。
- 構造函數只能使用
new
來調用。這樣的調用意味着在開始時創建空的this
,並在最後返回填充的對象。