好家伙,本篇為《JS高級程式設計》第八章“對象、類與面向對象編程”學習筆記 1.關於對象 ECMA-262將對象定義為一組屬性的無序集合。嚴格來說,這意味著對象就是一組沒有特定順序的值。 對象的每個屬性或方法都由一個名稱來標識,這個名稱映射到一個值。正因為如此(以及其他還未討論的原因),可以把 EC ...
好家伙,本篇為《JS高級程式設計》第八章“對象、類與面向對象編程”學習筆記
1.關於對象
ECMA-262將對象定義為一組屬性的無序集合。嚴格來說,這意味著對象就是一組沒有特定順序的值。
對象的每個屬性或方法都由一個名稱來標識,這個名稱映射到一個值。正因為如此(以及其他還未討論的原因),可以把
ECMAScript的對象想象成一張散列表,其中的內容就是一組名/值對,值可以是數據或者函數。
簡單使用一下
let object =new Object();
object.name ="panghu";
object.age ="20";
object.job ="student";
object.getName = function(){
console.log(this.name)
};
看圖:
也可以這樣寫,在這種字面量中,等號變為了冒號,分號變為了逗號
(顯然第二種更美觀,直接)
let object = {
name: "panghu",
age: "20",
job: "student",
getName() {
console.log(this.name)
}
}
object.getName();
看圖:
2.屬性類型
ECMA-262使用一些內部特性來描述屬性的特征。這些特性是由為JavaScript實現引擎的規範定義的。
因此,開發者不能在JavaScript中直接訪問這些特性。
為了將某個特性標識為內部特性,規範會用兩個中括弧把特性的名稱括起來,比如[[Enumerable]]。
屬性分兩種,數據屬性和訪問器屬性。
2.1.1.數據屬性
數據屬性包含一個保存數據值的位置。值會從這個位置讀取,也會寫入到這個位置。
數據屬性有4個特性描述它們的行為。
(是否可以修改"數據屬性",是否可遍歷,值是否可修改,值 就是這個四個)
□[[Configurable]]:表示屬性是否可以通過delete 刪除並重新定義,是否可以修改它的特性,以及是否可以把它改為訪問器屬性。
預設情況下,所有直接定義在對象上的屬性的這個特性都是true,如前面的例子所示。
□[[Enumerable]]:表示屬性是否可以通過for-in迴圈返回。
預設情況下,所有直接定義在對象上的屬性的這個特性都是true,如前面的例子所示。
□[[writable]]:表示屬性的值是否可以被修改。
預設情況下,所有直接定義在對象上的屬性的這個特性都是true,如前面的例子所示。
□[[Value]]:包含屬性實際的值。這就是前面提到的那個讀取和寫入屬性值的位置。
這個特性的預設值為undefined。
2.1.2.object.defineProperty()方法
使用object.defineProperty()方法修改屬性的預設特性
這個方法接收3個參數:要給其添加屬性的對象、屬性的名稱和一個描述符對象。
示例:
let person ={};
Object.defineProperty(person,"name",{
configurable:false,
value:"panghu"
})
console.log(person.name);
Object.defineProperty(person,"name",{
configurable:false,
value:"xiaofu"
})
console.log(person.name);
此處,將configurable屬性改為false後,不可再修改數據屬性,
(writable屬性同理,writable改為false後,不可再修改"值"的屬性)
(過河拆橋了屬於是)
2.2.訪問器屬性
訪問器屬性不包含數據值。(就像它的名字一樣,他是用來訪問的)
相反,它們包含一個獲取(getter)函數和一個設置(setter)函數,不過這兩個函數不是必需的。
在讀取訪問器屬性時,會調用獲取函數,這個函數的責任就是返回一個有效的值。
在寫入訪問器屬性時,會調用設置函數並傳入新值,這個函數必須決定對數據做出什麼修改。訪問器屬性有4個特性描述它們的行為。
(聯繫著上面那個一起記就好了)
□[[configurable]]:表示屬性是否可以通過delete 刪除並重新定義,是否可以修改它的特性,以及是否可以把它改為數據屬性。
預設情況下,所有直接定義在對象上的屬性的這個特性都是true。
□[[Enumerable]]:表示屬性是否可以通過for-in迴圈返回。
預設情況下,所有直接定義在對象上的屬性的這個特性都是true。
□[[Get]]:獲取函數,在讀取屬性時調用。預設值為undefined。
□[[set]]:設置函數,在寫入屬性時調用。預設值為undefined。
訪問器屬性是不能直接定義的,必須使用Object.defineProperty()。
書本中的原例:
let book = {
year_: 2017,
edition: 1
}
Object.defineProperty(book, "year", {
get() {
return this.year_;
},
set(newValue) {
if (newValue > 2017) {
//此時this指向book
this.year_ = newValue;
this.edition += newValue - 2017;
}
}
});
book.year = 2018;
console.log(book.edition);
這是訪問器屬性的典型使用場景,即設置一個屬性值會導致一些其他變化發生。
3.定義多個屬性
我們使用Object.defineProperty()去修改某個對象的屬性(數據屬性或訪問器屬性),
那麼,按照JS一貫的尿性,定義多個屬性大概使用"它的複數"方法 (這個改複數我會,去y加ies)
Object.defineProperties()方法:
let person = {};
Object.defineProperties(person, {
name_: {
value: "panghu"
},
age: {
value: "20"
},
name: {
getName() {
return this.name_;
},
}
})
console.log(person);
4.讀取屬性的特性
使用 Object.getOwnPropertyDescriptor()方法可以取得指定屬性的屬性描述符。
這個方法接收兩個參數::屬性所在的對象和要取得其描述符的屬性名。
返回值是一個對象,對於訪問器屬性包含configurable、enumerable、get和 set屬性,
對於數據屬性包含 configurable,enumerable.writable和value屬性。
(這個變複數我會,直接加s)
ECMAScript 2017 新增了 Object.getOwnPropertyDescriptors()靜態方法。
這個方法實際上會在每個自有屬性上調用object.getOwnPropertyDescriptor()併在一個新對象中返回它們。
兩個方法放同一個例子了:
let person = {};
Object.defineProperties(person, {
name_: {
value: "panghu"
},
age: {
value: "20"
},
name: {
get:function() {
return this.name_;
},
set:function(name){
this.name=name;
}
}
})
let descriptor_1 = Object.getOwnPropertyDescriptor(person,"name");
let descriptor_2 = Object.getOwnPropertyDescriptors(person);
console.log(descriptor_1);
console.log(descriptor_2);
5.合併對象
JavaScript 開發者經常覺得“合併”(merge)兩個對象很有用。
更具體地說,就是把源對象所有的本地屬性一起複制到目標對象上。
有時候這種操作也被稱為“混人”(mixin),因為目標對象通過混入源對象的屬性得到了增強。
ECMAScript6專門為合併對象提供了object.assign()方法。
這個方法接收一個目標對象和一個或多個源對象作為參數,
然後將每個源對象中可枚舉(object.propertyIsEnumerable()返回 true)和自有(Object.hasownProperty()返回true)屬性複製到目標對象。
以字元串和符號為鍵的屬性會被覆制。
對每個符合條件的屬性,這個方法會使用源對象上的[[Get]]取得屬性的值,然後使用目標對象上的[[Set]]設置屬性的值。
let book, person ,result;
book ={};
person ={ id:'999'};
result = Object.assign(book,person);
console.log(result);
console.log(book);
6.增強的對象語法
6.1.屬性值的簡寫
兩者等價
let name = "panghu";
let person ={
name:name
};
console.log(person);
簡寫:
let name = "panghu";
let person ={
name:name
};
console.log(person);
6.2.可計算屬性
在引入可計算屬性之前,如果想使用變數的值作為屬性,
那麼必須先聲明對象,然後使用中括弧語法來添加屬性。
換句話說,不能在對象字面量中直接動態命名屬性。
有了可計算屬性,就可以在對象字面量中完成動態屬性賦值。
中括弧包圍的對象屬性鍵告訴運行時將其作為JavaScript表達式而不是字元串來求值
示例如下:
const name_key ="panghu";
let person ={
[name_key]: "xiaofu",
}
console.log(person);
6.3.簡寫方法名
let person ={
name:"panghu",
getName: function(){
return this.name
}
}
person.getName();
let person ={
name:"panghu",
getName(){
return this.name
}
}
person.getName();
7.對象解構
ECMAScript6新增了對象解構語法,可以在一條語句中使用嵌套數據實現一個或多個賦值操作。
簡單地說,對象解構就是使用與對象匹配的結構來實現對象屬性賦值。
(簡單的說,就是拆開來用)
let person = {
name: "panghu",
age: "20",
};
let {
name: personName,
age: personAge
} = person;
console.log(personName);
console.log(personAge);
//簡寫版本
let {
name,
age
} = person;
console.log(name);
console.log(age);
註意:undefined和null不能被解構