检测属性

判断某个属性是否存在某个对象中,有3种方式

  1. in运算符
  2. hasOwnPreperty()
  3. propertyIsEnumerable()

in运算符

var o = {x:1,y:2};
x in o; //true
y in o;//true
toString in o; //true

hasOwnpreperty()

var o1 = {x:1,y:2};
o1.hasOwnProperty('x'); //true
o1.hasOwnProperty('y'); //true
o1.hasOwnProperty('toString'); //true

hasOwnProperty 方法对于继承属性会返回false,也就是hasOwnProperty()方法只能判断自有属性

propertyIsEnumerable

propertyIsEnumerable 是 hasOwnPreperty的增强版,只有检测到这个属性并且这个属性可枚举时才会返回true,也意味着继承的属性将返回false

怎么区分那些属性是否可枚举?

一般来说,某些内置的属性都不可枚举,比如Object.prototype 这个原型属性;
通常由javascript创建的代码一般都是可以枚举的,
也可以通过propertyIsEnumerable()这个方法判断对象属性是否可以枚举

propertyIsEnumerable 检测对象属性是否可以枚举

var o2 = {x:1};
o2.y = 1;
o2.propertyIsEnumerable('y'); //true

然而有一种场景只能使用in运算符,不能使用上述运算符

var o3 = {x:undefined};
o3.x !== undefined;
x in o3; //true 属性存在,但为undefined
y in o3; //false 属性不存在

这里的!== 并不是!= ,!==可以区分undefined 和 null

枚举属性

var o4 = {x:1,y:2,x:3};
o4.hasOwnProperty('toString'); 
//false 不可枚举属性,toString 是继承原型的,不是自有属性
for(val in o4 )console.info(val);

在es5之前新添加的方法是不可以定义不可枚举的,他们都可以通过for/in循环遍历,为了出现不必要的属性,可以通过以下两种方式过滤

for(v in o4){
    if(!o4.hasOwnProperty(v))continue;  //跳过继承的属性
}
for(v in o4){
    if(typeof(o4[v]) ===  'function')continue;  //方法
}

自有属性指的是对象本身的而不包括继承的属性

属性的特性

  1. 可写
  2. 可枚举
  3. 可配置

在es3中程序创建属性都是可枚举,可写,可配置的,es5才增加这些特性的api

检测一个属性是可写还是可配置还是可枚举?

Object.getOwnPropertyDescriptor({x:1},'x'); //返回描述符对象
Object {value: 1, writable: true, enumerable: true, configurable: true}

设置属性的描述符Object.defineProperty()

var o5 = {x:1};
Object.defineProperty(o5,x,{
    value:2,    //设置值为2
    enumerable:true,    //可枚举
    configurable:true   //可配置
});

对象的三个属性 prototype , 类属性 ,扩展属性

查询某个对象的原型对象Object.getPrototypeOf()

var p  = {x:1};
var o = Object.create(p);
var test = Object.getPrototypeOf(o); //p对象

查询某个对象的原型对象Object.getPrototypeOf()

var p1 = {x:1};
var obj = Object.create(p1);
p1.isPrototypeOf(obj); ///true 检查p1是否是obj的原型
Object.prototype.isPrototypeOf(obj);//true 继承自Object.prototype