对象的比较
对象的比较都是引用的比较,因此,在比较对象的属性和值是否全等时,不能直接比较。通常要用 JSON.stirngify() 转为字符串后,再比较字符串。
var arr1 = [1,2],arr2 = [1,2];
console.log(arr1 === arr2);//false
console.log(JSON.stirngify(arr1) === JSON.stirngify(arr2));//true
var a = {}, b = {}, c = {};//a、b、c每个都引用一个不同的空对象
a = b = c = {};或c = {}; b = c; a = b; //a、b、c都引用同一个空对象
数据属性
数据属性有四个描述其行为的特性:
- [[configurable]]:表示是否能够通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。当直接在对象上定义属性时,这个值默认为true
- [[Enumerable]]:表示能否通过for-in循环返回属性。当直接在对象上定义属性时,这个值默认为true
- [[Writable]]:表示能否修改属性的数据值Value。当直接在对象上定义属性时,这个值默认为true
- [[Value]]:包含这个属性的数据值。这个特性默认值为undefined。
要修改属性的默认特性的值,必须使用 Object.defineProperty() 或 Object.defineProperties() 方法修改(一个或多个特性)。这个方法接收三个参数:属性所在的对象、属性的名字和一个描述符对象。 而由Object.defineProperty() 或 Object.defineProperties() 创建的特性,默认值都为 false。
var person = {
name:'wang',
age:18
};
Object.defineProperty(person,'name',{
writable:false;
});
person.name = 'li';
alert(person.name);//wang
访问器属性
访问器属性不包含数据值,它们包含一对 getter 和 setter 函数(不过,这两个函数也不是必须的)。 访问器属性有四个特性:
- [[configurable]]:表示是否能够通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为数据属性。当直接在对象上定义属性时,这个值默认为 true。
- [[Enumerable]]:表示能否通过 for-in 循环返回属性。当直接在对象上定义属性时,这个值默认为 true。
- [[Get]]:在读取属性时调用函数。默认值为 undefined。
- [[Set]]:在写入属性时调用的函数。默认值为 undefined。
注:访问器中没有 Writable 和 Value 这两个特性,因此不要设置这两个的值,否则出错。
var book = {
_year : 2004,
edition : 1
};
Object.defineProperty(book,"year",{
get : function () {
alert(this._year);
},
set : function (newValue) {
if (newValue > 2004) {
this._year = newValue;
this.edition += newValue - 2004;
}
}
});
book.year; // 弹出窗口,显示 2004
book.year = 2005;
console.log(book.edition); // 2
专门读取数据属性和访问器属性的特性的值的方法: Object.getOwnPropertyDescriptor(),这个方法接收两个参数,属性所在的对象和属性名称。
var girl = {name: "zyj"};
console.log(Object.getOwnPropertyDescriptor(girl,"name"));
// Object {value: "zyj", writable: true, enumerable: true, configurable: true}
Object.defineProperties(girl,{
name:{
writable: false
},
age:{
writable: true,
value: 22
}
});
console.log(Object.getOwnPropertyDescriptor(girl,"name"));
// Object {value: "zyj", writable: false, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(girl,"age"));
// Object {value: 22, writable: true, enumerable: false, configurable: false}
var descriptor = Object.getOwnPropertyDescriptor(girl,"age");
console.log(descriptor.value); // 22
console.log(descriptor.configurable); // false
console.log(descriptor.writable); // true
console.log(descriptor.get); // undefined
console.log(descriptor.set); // undefined
对象的扩展、密封及冻结三大特性
扩展特性
Object.isExtensible(obj)
:判断一个对象是否可扩展(即是否可添加新属性)Object.preventExtensions(obj)
:让一个对象变得不可扩展。(仍可为该对象的原型添加新属性)
密封特性
密封对象是指那些不能添加新的属性,不能删除已有属性,以及不能修改已有属性的可枚举性、可配置性、可写性,但可能可以修改已有属性的值的对象。
Object.isSealed(obj)
:判断一个对象是否是密封对象。Object.seal(obj)
:将一个对象密封。
冻结特性
冻结对象是指那些不能添加新的属性,不能修改已有属性的值,不能删除已有属性,以及不能修改已有属性的可枚举性、可配置性、可写性的对象。也就是说,这个对象永远是不可变的。
Object.isFrozen(obj)
:判断是否是冻结对象Object.freeze(obj)
:把一个对象冻结
如果一个冻结对象的属性也是一个对象,那么这个对象的引用地址是不能变的,但属性是可变的。所以如果要彻底地冻结一个对象及其所有属性(一般称为深度冻结),则要递归遍历对象,把每一个对象属性也冻结。
Object.deepFreeze = function(obj) {
var propNames = Object.getOwnPropertyNames(obj);
propNames.forEach(function(name) {
var prop = obj[name];
if (typeof prop === 'object' && prop !== null) {
Object.deepFreeze(prop);
}
});
return Object.freeze(obj);
}