全面了解JavaScript对象进阶(2)

delete只能删除自有属性,不能删除继承属性。要删除继承属性,必须从定义这个属性的原型对象上删除它,而且这会影响到所有的继承自这个原型的对象。删除成功会返回true。

ar o = {x: 1}; delete o.x; //删除x,返回true delete o.x; //x已经不存在了,什么都没做,返回true。 delete o.toString; //什么都没做,返回true。 delete不能删除可配置型为false的属性。某些内置对象的属性是不可配置的,比如通过变量声明和函数声明创建的全局对象的属性: delete Object.prototype //不能删除,属性是不可配置的 var x = 1; delete this.x; //不能删除这个属性 function f() {} delete this.f; //不能删除全局函数

2.3 检测属性

判断某个属性是否存在于某个对象中,可通过in运算符、hasOwnProperty()和propetyIsEnumerable()方法来检测。

in运算符:运算符左侧是属性名,右侧是对象。如果对象的自有属性或者继承属性包含属性则返回true:

var o = {x: 1}; "x" in o; //true:x是o的属性 "y" in o; //false:y不是o的属性 "toString" in o; //true:o继承toString属性

hasOwnProperty()方法:检测给定的名字是否是对象的自有属性。对于继承属性它将返回false:

var o = {x: 1}; o.hasOwnProperty("x"); //true:o有一个自由属性x o.hasOwnProperty("y"); //false:o中不存在属性y o.hasOenProperty("toString"); //false:toString是继承属性

propertyIsEnumerable()方法:是hasOwnProperty的增强版,只有检测到自有属性并且这个属性是可枚举行为true时才返回true:

var o = inherit({y: 2}); o.x = 1; o.propertyIsEnumerable("x"); //true: o有一个可枚举属的自有属性x o.propertyIsEnumerable("y"); //false:y是继承来的 Object.prototype.propertyIsEnumerable("toString"); //false:不可枚举

2.4 枚举属性

通常使用for/in循环遍历对象属性,遍历的属性包括自有属性和继承属性。对象继承的内置方法是不可枚举的,但在代码中给对象添加的属性都是可枚举的。例如:

var o = {x: 1, y: 2, z: 3}; //三个可枚举的自有属性 o.propertyIsEnumeable("toString"); //false,不可枚举 for (p in o) //遍历属性 console.log(p); //输出x、y和z,不会输出toString

有时候我们只想遍历自有属性,并且属性不为函数:

for(p in o){ if(!o.hasOwnProperty(p)) continue; if(typeof o[p] === "function") continue; }

我们可通过枚举遍历功能实现可枚举属性的复制:

/* * 把p中的可枚举属性复制到o中,并返回o * 如果o和p含同名属性,则覆盖o中的属性 * 这个函数并不处理getter和setter以及复制属性 */ function extend(o, p){ for(prop in p){ //遍历p中的所有属性 o[prop] = p[prop]; //将属性添加到o中 } return o; }

ES5定义了两个用以枚举属性名称的函数。第一个是Object.keys(),返回由对象中可枚举属自有属性名称组成的数组。第二个枚举函数是Object.getOwnPropertyNames(),和Object.keys()类似,它返回对象的所有自有属性,而不仅仅是可枚举属性。

3.属性封装

3.1 属性getter和setter 

对象属性由名字、值和一组特性(attribute)构成的。在ES5中,属性值可以用一个或两个方法替代,这两个方法就是getter和setter。由getter和setter定义的属性称做“存取器属性”,它不同于“数据属性”,数据属性只有一个简单的值。

和数据属性不同,存取器属性不具有可写性(writeable atribute)。如果属性同时具有getter和setter方法,那么它是一个读/写属性。如果它只有getter方法,那么它是一个只读属性,如果它只有setter方法,那么它是一个只写属性。读取只写属性总是返回undefined。

存取器属性定义语法也比较简单,函数定义没有使用function关键字,而是使用get或set:

var o = { //普通的数据属性 data_prop: 1, //存取器属性都是成对定义的函数 get accessor_prop(){/* 这里是函数体 */}, set accessor_prop(value){} };

思考下面这个表示2D笛卡尔点坐标的对象。它有两个普通属性x和y分别表示x坐标和y坐标,它还有两个等价的存取器属性用来表示点的极坐标:

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); var ratio = newValue / oldValue; this.x *= ratio; this.y *= ratio; }, //theta是只读存取器属性,只有getter方法 get theta() { return Math.atan2(this.y, this.x); } };

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wzsyfs.html