上文中提到JavaScript对象是属性的集合,本结就来谈谈对象的属性以及对属性的操做。我的认为,JavaScript中对象的属性比其余语言复杂不少,因为本屌的主业是PHP,所以当初看书时候也花了不少时间才把这部份内容给理清了。javascript
跟传统的面向对象不太同样,JavaScript对象是动态的,便可以随时对一个js对象新增或删除属性,对属性最多见的操做是设置、查找、删除、检测、枚举。除此之外,每一个属性还有一些与之相关的值,称为“属性特性”:java
正是因为上述3中属性特性使得JavaScript中属性相对其余语言来讲复杂了不少。此外,根据属性的定义位置,能够把属性分为:数组
因为对象的属性一部分是由本身定义,还有一部分属性是从原型对象那继承下来,所以假如要查询对象o中的属性x时,若是o中不存在,js引擎将会陆续在o的原型对象中来寻找x,若是整条原型链中都找不到或者找到一个原型是null的对象,则返回undefined函数
var o = {}; o.x = 1; p = inherit(o); //建立一个新对象p,原型对象为o,inherit函数请查看上一篇 console.log(p.x); //返回1,因为在对象p中找不到属性x,则js引擎在它的原型对象中继续查找
如今假设给给对象o的属性x赋值,若是o中以及有自有属性x,则赋值操做值就直接改变该属性的值,若是不存在,则赋值操做给o新增这个属性x。若是o中的原型链中也有该属性,则继承的属性就被这个新建立的属性覆盖了。this
上述对属性的赋值是基于一种理想状况,事情每每不会那么简单,上面以及提到,每个属性都有3个属性特性:可写、可枚举、可设置,若是对象o中继承了一个只读属性的x,则赋值操做是不被容许的。spa
在JavaScript中,只有在查询属性时,才能体会到继承的存在。code
删除一个JavaScript对象的属性可使用delete运算符,然而须要注意的是:delete只是断开属性和宿主对象的联系,而不会去操做属性中的属性,在销毁一个对象时应特别注意这点;此外delete只能删除自有属性,不能删除继承属性,所以若是要删除继承属性,须要先找到原型链中的该拥有该属性的对象才能删除它。对象
若是碰到那种可配置性为false的属性,如经过变量声明或函数声明建立的全局的对象,是不能被删除的,在严格模式下,删除一个不可配置的属性会报一个类型错误。blog
检测一个属性是否属于某个对象有如下几种方法:继承
var o ={}; o.x = 1; p = inherit(o); p.y = 2; o.hasOwnProperty("x"); //返回true p.hasOwnProperty("x"); //返回false Object.property.propertyIsEnumerable("toString"); //返回false,toString()方法不可枚举
经过for/in循环能够遍历出对象中全部可枚举的属性(包括自有属性和继承属性),通常来讲,对象的内置方法是不可枚举的,但在代码中定义的属性一般都是能够枚举,除非显式地指定该属性为不可枚举,例如:
var o ={x:1 , y:2, z:3}; o.propertyIsEnumerable("toString"); //返回false for(p in o){ console.log(p); } //循环输出1,2,3,但不会输出toString.
在ECMAScript5中定义了两个用于枚举属性名称的函数Object.keys()和Object.getOwnPropertyNames(),前者返回一个由对象中可枚举且自有属性组成的数组,后者也返回一个数组,可是它返回的是自有属性的名称,无论其是否可枚举,在ECMAScript3中能够用如下方法来模拟前者:
1 function keys(o){ 2 if(typeof o !== "object") throw TypeError(); 3 var result = []; 4 for(prop in o){ 5 if (!o.hasOwnProperty(prop)) continue; 6 else result.push(prop); 7 } 8 return result; 9 }
在ECMAScript5中,属性值能够用一个或两个方法替代,这两个方法就是getter和setter,由这两个方法定义的属性称做“存取器属性”,不一样于“数据”属性,它不具备写属性。
若是一个存取器属性同时具备getter和setter方法,则这个属性是可读写的,若是只有getter那么它就是个只读属性;若是只有setter方法,则是一个只写属性,读取它时返回undefined
var o ={ x : 2, y : 3, get z(){ return this.x*this.y; }, set z(value){ this.x += value; this.y += value; } }; console.log(o.z); //返回6 o.z = 2; console.log(o.z); //返回20