內容簡介:JavaScript是物件導向語言,透過原型機制實現繼承,透過『閉包』等方式可以實現封裝。 本文來探討JavaScript物件的特殊之處:原型鏈、引用、反射、屬性遍歷等特性。
一、物件建立
JavaScript擁有非常直覺的物件建立方式:
var emptyObject = {};
var person = {
name: 'harttle',
}
name: 'harttle',
} Object();
xx.name = 'hartle';
xx.age = 24;
二、屬性存取
屬性可以透過兩種語法存取:
person.age
person['age']
當屬性名稱不符
存在時JavaScript會沿著原型鏈去找。 賦值可以更新或建立一個屬性,屬性可以透過delete person.age來刪除。
對undefined獲取屬性會引發TypeError,一般透過&&解決:
// person.girl === undefined
person.girl.name;
三、原型
JavaScript的原型繼承方式有些繁瑣,在ES6中提供了Object.create方法,原型繼承變得更加簡單。
它的實現大致是這樣的:
if (typeof Object.create !== 'function') {
Object.create = function (o) {
;
return new F();
};
}
var obj = Object.create(proto);
如果被賦值/移除的屬性來自於為當前原型,Java
如果被賦值/移除的屬性來自於為當前原型,Java
如果已刪除的屬性。屬性不會受到影響。
網傳person.age = undefined來刪除屬性的方式,其實相當於建立一個屬性,其值為undefined。而delete person.age則會真正刪除屬性,就像從未聲明過那個屬性一樣。
例如:
var prot = { name: 'harttle' };
// 以prot 為原型建立p
var p = Object.create(prot);
delete p.name harttle', 原型鏈的物件屬性不受影響
p.name = undefined; // p.name === undefined
delete p.name;
undefined屬於基本資料型別Undefined,該型別的取值只有一種,即undefined。
四、物件引用
JavaScript中物件是透過引用傳遞的,它們不會被拷貝:
var a = b = {};
a.name = 'harttle';
b.name === 'harttle' /harttle';
b.name === 'harttle' / / true
經由原型繼承時,原型也是作為引用進入原型鏈的,原型屬性不會被拷貝:
var prot = {girl: {name: 'alice'}};
var p1 = Object.create(prot) ;
var p2 = Object.create(prot);
p1.girl.name = 'fuck'; // p2.girl.name === 'fuck'
可見原型關係是動態關係。
五、反射
JavaScript是一門動態語言,透過typeof可以在運作時取得類型資訊:
typeof p.age // 'number'
function',來自原型:Object.prototype
typeof p.wing // 'undefined'
當然,typeof的能力有限,且只能檢查基本資料類型。 為了支援物件導向設計,我們需要更複雜的類型判斷機制,可以參考 如何檢查JavaScript的類型?一文。
六、屬性遍歷
可以透過for in遍歷物件屬性(包含原型屬性):
var person = {name: 'harttle', age: 24};
for(var prop in person){
for(var prop in person){
[prop);
}
為了只取得目前物件的屬性,可以透過hasOwnProperty來判斷:
for(var prop in person){
if(person.hasOwnProperty(prop)){
;
}
}
for in不保證屬性的順序,如果需要保證順序可以使用Array來代替。 也避免了判斷來自原型的屬性。 🎜七、避免全域變數 🎜對全域變數的依賴是JavaScript的設計缺陷之一。避免使用全域變數有很多方法, 其中最簡單的就是為你的專案定義一個全域變量,並且只定義一個全域變數:
var APP = {};
APP.foo = 'xxx';
APP.bar = 'xxx';
這樣程式碼更容易維護和變更,畢竟APP.foo一眼看去就是一個全域變數。