- 检测属性
js对象可以看成是属性的集合,判断某个属性是否存在于某个对象中,可以通过in,hasOwnPreperty()和propertyIsEnumerable()方法来完成这个工作。
in左侧是属性名,右侧是对象。如果对象的自有属性或者继承属性中包含这个属性则返回true.
var o={x:1}
"x" in o;//true "x" 是o的属性
"y" in o;//false
"toString" in o;//true
hasOwnProperty()方法检测是否是对象的自有属性。对于继承属性返回false
var o={x:1}
o.hasOwnProperty("x");//true 自有属性x
o.hasOwnProperty("y");//false
o.hasOwnProperty("toString");//false
propertyIsEnumerable()只有检测到是自有属性且属性的可枚举性是true时才返回true。通常由js创建的属性是可枚举的。
var o=inherit({y:2});
o.x=1;
o.propertyIsEnumerable("x");//true o有一个可枚举的自有属性x
o.propertyIsEnumerable("y");//false y是继承来的
Object.prototype.propertyIsEnumerable("toString");//false 不可枚举
除了in运算符之外,还有一个使用“!==”判断一个属性是否是undefined
var o={x:1}
o.x!==undefined;//true o中有属性x
o.y!==undefined;//false o中没有属性Y
o.toString!==undefined;//true o继承了toString属性
in可以区分属性不存在和存在但是值为undefined. !==可以区分undefined 和null
//特殊场景,只能用in,不能用!==
var o={x:undefined}
o.x!==undefined;//false 属性存在,但值为undefined
o.y!==undefined;//false 属性不存在
"x" in o //true 属性存在
"y" in o //false 属性不存在
delete o.x; //删除了属性x
"x" in o //false 属性不在存在
- for/in可以便利对象中所有可枚举的属性(包括自有属性和继承属性)
Object.keys() 返回一个数组,这个数组由对象中可枚举的自有属性名称组成
Object.getOwnPropertyNames() 返回对象的所有自有属性名称 - 存取器属性getter setter
查询存取器属性时,调用getter方法,返回属性存取表达式的值。当程序设置一个存取器属性值是,调用setter方法。读取只写属性总是返回undefined
var p={
//x和y时普通的可读写的数据属性
x:1.0;
y:1.0;
//r是可读写的存取器属性,它具有getter和setter
//函数体结束后不要忘记逗号
get r(){ return Math.sqrt(this.x*this.x+this.y*this.y);},
set r(newvalue){
var oldvalue=Math.sqrt(this.x*this.x+this.y*this.y);
var ratio=newvalue/oldvalue;
this.x*=ratio;
this.y*=ratio;
},
//theta 是只读存取器属性,它只有getter方法
get theta(){ return Math.atan2(this.y,this.x);}
};
上述代码中,js把函数当做对象的方法调用,也就是说,函数体内的this指向表示这个点的对象。
存取器属性是可以继承的。
var q=inherit(p);//创建一个集成getter和setter的新对象
q.x=1,q.y=1;//给q添加两个属性
console.log(q.r);//可以使用继承的存取器属性
console.log(q.theta);
- 属性描述符property description
数据属性的描述符对象的属性有value writable enumerable configurable
存取属性描述符对象则用get 和set代替value 和writable
Object.getOwnPropertyDescriptor()获得某个对象特定的自有属性描述符。对于继承属性和不存在的属性,返回undefined
调用Object.defineProperty() 传入要修改的对象,要创建或修改的属性名称以及属性描述符对象
var o={};//创建一个空对象
//添加一个不可枚举的数据属性,并复制为1
Object.defineProperty(o,"x",{
value:1,
writable:true,
enumerable:false,
configurable:true
});
//属性是存在的 但不可枚举
o.x;//1
Object.keys(o)//[]
//对属性修改变为只读
Object.defineProperty(o,"x",{writable:false});
//试图修改这个属性的值
o.x=2;//操作失败但不报错,在严格模式中抛出类型错误异常
o.x //1
//属性依然是可配置的,因此可以通过这种方式修改
Object.defineProperty(o,"x",{value:2});
o.x //2
//现在将x从数据属性修改为存取器属性
Object.defineProperty(o,"x",{get:function(){return 0;}});
同时修改或创建多个属性,则需要使用Object.defineProperties(),第一个参数是要修改的对象,第二个参数是映射表
//从一个空对象开始,添加两个数据属性和一个制度存取器属性
var p=Object.defineProperties({},{
x:{value:1,writable:true.enumerable:true,configurable:true},
y:{value:1,writable:true.enumerable:true,configurable:true},
r:{
get: function(){return Math.sqrt(this.x*this.x+this.y*this.y)},
enumerable:true,
configurable:true
}
});
- 原型属性
通过对象直接量创建的对象使用Object.prototype作为它们的原型,通过new创建的对象使用构造函数prototype属性作为它们的原型。通过Object.create()创建的对象使用第一个参数(也可以是null)作为它们的原型。
Object.getPrototypeOf()可以查询它的原型
要想检测一个对象是否是另一个对象的原型,使用isPrototypeOf()方法
//检测p是否是o的原型
var p={x:1};//定义一个原型对象
var o=Object.create(p);//使用这个原型创建一个对象
p.isPrototypeOf(o) //true o继承自p
Object.prototype.isPrototypeOf(o) //true p继承自Object.prototype
- 类属性
要想获得对象的类,可以调用对象的toString()方法,返回如下格式的字符串[object class],然后提取已经返回字符串的第8个到倒数第二个位置之间的字符
由于很多对象继承的toString()方法重写了,必须间接的调用Function.call()方法。classof()函数可以返回传递给它的任意对象的类
function classof(o){
if (o===null) return "NULL";
if (o===undefined) return "Undefined";
return Object.prototype.toString.call(o).slice(8,-1);
}
- 可扩展性 Object.esExtensible()判断对象是否是可扩展的
- 对象的方法
toString()方法:返回一个表示调用这个方法的对象值的字符串
toLocaleString()方法:返回一个表示这个对象的本地化字符串