var descriptor = Object.getOwnPropertyDescriptor({ length: 50 }, "length"); console.log(descriptor); //=> descriptor = { value: 50, writable: true, enumerable: true, configurable: true } //------------------------------------------------------------------ var random = { //只读属性:返回一个0-255之间的随机数 get octet() { return Math.floor(Math.random() * 256); } }; var descriptor1= Object.getOwnPropertyDescriptor(random,"octet"); console.log(descriptor1); //=> descriptor1 = Object {set: undefined, enumerable: true, configurable: true}
从名字可以看出该方法只能得到对象自有属性的描述符,所以对于继承属性和不存在的属性,返回undefined。要获得继承属性的特性,需要遍历原型链。
要想设置属性或让新创建属性具有某种特性,则需要调用Object.defineProperty()方法,第一个参数是要修改的对象;第二个参数是要修改的属性;第三个是属性描述符对象。返回值为修改后的对象副本。
var o = {}; //创建一个空对象 Object.defineProperty(o, "x", { value: 1, //定义一个x属性,赋值为1 writable: true, //可写 enumerable: false, //不可枚举 configurable: true //可配置 }); if (o.x) console.log(Object.keys(o)); //=> props = [] 属性存在,但是不能枚举 Object.defineProperty(o, "x", { writable: false }); //让属性x变为只读 o.x = 2; //试图修改属性x的值失败,但不报错 console.log(o.x); //=>1 Object.defineProperty(o, "x", { value: 2 }); //但属性x依然为可配置,可以直接修改value值特性。 console.log(o.x); //=>2 Object.defineProperty(o, "x", { //将数据属性修改为存取器属性 get: function () { return 0; } }); console.log(o.x); //=>0
该方法同样不能设置继承属性的特性。如果需要同时修改多个自有属性的特性可以使用Object.defineProperties()方法。第一个参数是要修改的对象;第二参数是一个映射表对象,它包含属性名称和对应属性的描述符对象。
var p = Object.defineProperties({}, { x: { value: 3, writable: true, enumerable: true, configurable: true }, y: { value: 4, writable: true, enumerable: true, configurable: true }, r: { get: function () { return Math.sqrt(this.x * this.x + this.y * this.y); }, enumerable: true, configurable: true } }); console.log(p.r); //=>5
7.对象的三个属性
原型属性
对象的原型是用来继承属性的,这个属性非常重要,以至于经常把“o的原型属性”直接叫做“o的原型”。
原型属性是在对象创建之初就设置好的。前面已对原型做过介绍,但这里还是要补充补充。
通过对象直接量创建的对象使用Object.prototype作为原型;
通过new关键字创建的对象使用构造函数的prototype作为原型;
通过Object.create()创建的对象使用第一个参数作为原型。
在ES5版本中,将对象传入Object.getPrototypeOf()方法可以查询它的原型对象。
想要检测一个对象是否是另一个对象的原型可以使用isPrototypeOf()方法。
var a = { x: 2 }; var b = Object.create(a); console.log(a.isPrototypeOf(b)); //=> true console.log(Object.prototype.isPrototypeOf(b));//=> true
类属性
对象的类属性是一个字符串,用来表示对象的类型信息。但是JS中没有提供直接查询方法,只能用一种间接的方法查询,可以调用对象的toString()方法,然后提取返回字符串的第8个字符至倒数第二个位置之间的字符。如果对象继承的toString()方法重写了,这时必须间接通过Function.call()方法调用。
function classof(o) { if (o === null) return "Null"; if (o === undefined) return "Undefined"; return Object.prototype.toString.call(o).slice(8,-1); }
classof()可以接收任何类型的参数,并且该函数包含了对null和undefined的特殊处理。
console.log(classof(null)); //=> "Null" console.log(classof(1)); //=> "Number" console.log(classof("")); //=> "String" console.log(classof(false)); //=> "Boolen" console.log(classof({})); //=> "Object" console.log(classof(/./)); //=> "Regexp" console.log(classof(window)); //=> "Window"(浏览器宿主对象类)
可扩展性
对象的可扩展行用来表示是否可以给对象添加新属性。ECMAScript 5版本中,所有自定义对象、内置对象和宿主对象默认支持可扩展性。下面介绍几个检测和设置对象可扩展性的方法以及它们之间的区别。