物件是特性(property,具有名稱和值,name:value pairs)的無序集合。
每個JavaScript物件都有第二個JavaScript物件(prototype),第一個物件即是從prototype繼承特性
var ary = new Array(1,2,3)
用New Array()創建物件,其原型是Array.prototype
除了Object.protorype沒有原型物件外(無繼承任何特性),其他原型物件(prototype)都具有原型的正常物件。所有內建的建構式(constructor)都有個繼承Object.prototype的原型。
function inherit(p){
if(p == null) throw TypeError();
if(Object.create) return Object.create(p); // Objcet.creat是ES5的語法
var t = typeof p;
if(t !== "Object" && t !== "function") throw TypeError();
function f(){}
f.protorype = p;
return new f();
}
//-----------
var obj={ x:"dont change this value"};
lib_function(inherit(obj)); // 防止對obj的修改
JavaScript物件有一組自有特性(own properties),同時也從原型物件繼承了一組特性。
var obj_1 = {x:5};
var obj_2 = Object.create(obj_1);
obj_2.y = 9;
obj_2.x; // return 5
以下例子可以看出
obj_2 在指定x=8並沒有修改到原本的物件,而是在自己的物件新增一個property。
var book ={};
book.title; // return undefined
book.title.length // thorw TypeError
為什麼book.title.length會throw TypeError,但book.title卻return undefined ?
因為當執行book.title是在取property,因為title未初始化,所以return undefined。
當執行book.title.length,會先去取title物件然後再取length property,所以在取title物件時,因為沒有這物件所以會throw TypeError。
var len = book && book.title && book.title.length;
以 var obj ={x:5};
來做解釋
in 運算子
var obj ={x:5};
"x" in obj; // return true
"y" in obj; // return false
"toString" in obj; //return true
判斷property是否存在可判斷是否為undefined即可,並非一定要用in。
obj.y !== undefined
var obj={x: undefined};
obj.x !== undefine; //return false;property存在但值為undefined
"x" in obj; // return true
在上面這情況下判斷"x" property是否存在於obj,用in判斷比較合理。
hasOwnProperty(): 僅測試自身擁有的property,不會往原型鍊找。
var obj ={x:5};
obj.hasOwnProperty("x"); // return true
obj.hasOwnProperty("y"); // return false
obj.hasOwnProperty("toString"); // return false
porpertyIsEnumerable(): 更完善的hasOwnProperty(),判斷自有的property且是enumerable
var obj= {x:5};
var objA= Object.create(obj);
objA.y= 9;
objA.porpertyIsEnumerable("x") // return false,非自有property
objA.porpertyIsEnumerable("y") // return true,自有property
Objcet.property.porpertyIsEnumerable("toString") // return false,自有property但非enumerable
列出property有兩個函式
Objcet.keys()
// 回傳可列舉自有propertyObject.getOwnPropertyNames()
// 回傳全部(不管是否可列舉)自有property。object裡面key-value pair的value可用getter與setter取代。
當property 只有setter時,代表只有寫入特性(如嘗試著取值得會得到undefined)。
當property 只有getter時,代表只有讀取特性。
當property有setter與getter時,代表有讀寫特性。
var obj ={
x:3,
y:3,
set r(v){
this.x=v;
this.y=v;
},
get r(){
return this.x * this.y;
}
}
// -----
var p = Object.create(obj);
p.r = 5;
在資料特性有四個屬性分別是value、writable、enumerable、configurable。
在accessor(getter/setter)特性沒有value(運用了get取代了)、writable(取決於有沒有setter),所以包含的屬性有get、set、enumerable、configurable。
var obj={}
Object.defineProperty(obj,"x",{ value:5,
wirtable: true,
enumerable: false,
configurable: true
})
obj.x; //return 5
obj.keys(); //return [] , 因為enumerable:false
// 修改為writable:false
Object.defineProperty(obj,"x",{ wirtable:false });
obj.x = 9; // 無聲無息的錯誤,在strict下會throw TypeError
// 因為configurable:true,所以可以用配置的方式給值
Object.defineProperty(obj,"x",{ value:9 });
obj.x; //return 9
// 改為accessor特性
Object.defineProperty(obj,"x",{ get: function(){return 1;} });
obj.x; //return 1