如果o继承了x属性,而x属性恰好是一个存取器属性(参见6.6)那么如果设置o.x=2是不会创建属性的,也不会修改父类的值,只会修改本类的值。
var a ={
x:1,
get r(){return this.x},
set r(value){this.x = value}
}
var b = Object.create(a);
b.r = 2; //这个操作修改了b中x的值
b.x //2
a.x //因为b中的操作只会修改b的值,所以a.x值不会变。
检测属性是否在对象中。
in/ !==:()
属性名 in 对象
var o = {x:1}
"x" in o //true
o.x !== undefined; //true
"y" in o //false
o.y !== o //false
"toString" in o //true o继承toString属性
o.toString !== o //true o继承toString属性
有一种情况in和!==不同,即属性值为undefined的时候,"x" in o 为true o.x !== undefined 为false。
检测属性是否为对象的自有属性(非继承)
hasOwnProperty():
o.hasOwnProperty("x"); //true
o.hasOwnProperty("y"); //false
o.hasOwnProperty("toString") //false toString是继承属性
检测属性是否为对象的自有属性,并且属性是否为可枚举的
propertyIsEnumerable():
o.propertyIsEnumerable("x"); //true o有一个可枚举的自有属性x
object.prototype.propertyIsEnumerable("toString"); //false:不可枚举
见128页6.4
------------------------------------------------16.10.13 结束---------------------------------------------------------------------------
-----------------------------------------------16.10.15 开始---------------------------------------------------------------------------
枚举属性
for/in循环可以遍历继承来的属性
见130页上
Object.getOwnPropertyNames(o); // 获取对象的所有自有属性。
见132页上
-----------------------------------------------16.10.15 结束---------------------------------------------------------------------------
-----------------------------------------------16.10.16 开始---------------------------------------------------------------------------
getter和setter
和数据属性不同,由getter和setter定义的为存取器属性
var o = {
x:1,
get r(){ return this.x},
set r(value) { this.x = value},
}
o.r //1
o.r = 2;
o.r //2
此时r这个属性是可读可写的,如果我们将set去掉。不管怎么给o.r赋值,o.r的属性一直都是不变的。但是在非严格模式下是不会报错的。同理,去掉get以后就无法获取属性值,o.r的值就为undefined。
见132页6.6
var a= {
$n = 0 //$符号暗示这个属性是一个私有属性
}
a.n //undefined
见134页上
属性的特性(API对库开发者来说非常重要)因为:
1、 可以通过这些API给原型对象添加方法,并将它们设置成不可枚举的,这让它们看起来更像内置方法。
2、可以通过这些API给对象定义不能修改或删除的属性,借此“锁定”这个对象。
属性的4个特性(‘属性描述符’对象):
1、数据属性:值(value)、可写性(writable)、可枚举性(enumerable)、可配置性(configurable)
2、存取器属性:读取(get)、写入(set)、可枚举性、可配置性
通过Object.getOwnPropertyDescriptor()可以获得某个对象特定属性的属性描述符:
Object.getOwnPropertyDescriptor({x:1},"x") // 返回{value:1, writable:true, enumerable:true, configurable:true}
Object.getOwnPropertyDescriptor(o,"r") //查询上面定义的o的r属性,返回{get:/*func*/, set:/*func*/, enumerable:true, configurable:true}
如果属性不存在,或者为继承属性,则返回undefined
见134页6.7
设置属性特性:
var o = {}
Object.defineProperty(o,"x",{ value:1,
writable:true,
enumerable:false,
configurable:true});
//给o对象添加一个不可枚举的数据属性x,并赋值为1
Object.keys(o) //因为o的x属性是不可枚举的,所以返回空数组[]
Object.defineProperty(o,"x",{writable:false}); //将x属性变成只读
o.x = 2 //操作失败,但在非严格模式中不会报错
o.x //为1
Object.defineProperty(o,"x",{value:2}) //因为属性依然是可配置的,所以可以通过这种方法进行修改
Object.defineProperty(o,"x",{get:function(){return 0;}}); //还可以将x从数据属性改为存取器属性
o.x //输出0
从上面可以看出来Object.defineProperty()的属性描述符参数对象不需要包含所有的4个特性,如果是新创建的,那么默认的就是false或者undefined。如果是修改的,那么就只修改设置的。
注意:这个方法要么修改已有属性,要么新建自有属性,并不能修改继承属性。
见135页中下
同时修改或创建多个属性:
var o = {};
Object.defineProperties(o,{
x:{value:1, writable:true, enumerable:true, configurable:true},
y:{value:2, writable:true, enumerable:true, configurable:true},
r:{
get:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},
enumerable:true,
configurable:true
}
});
见136页中
Object.defineProperty()和Object.defineProperties()使用规则:
1、如果对象是不可扩展的(参见6.8.3节),则可以编辑已有的自有属性,但不能给它添加新属性。
2、如果属性是不可配置的,则不能修改它的可配置性和可枚举性。
3、如果存取器属性是不可配置的,则不能修改其getter和setter方法,也不能将它转换为数据属性。
4、如果数据属性是不可配置的,则不能将它转换为存取器属性。
5、如果数据属性是不可配置的,则不能将它的可写性从false修改为true,但可以从true修改为false。