但是在ECMAScript 3中,没有Object.getPrototypeOf()函数,但经常使用表达式obj.constructor.prototype来检测一个对象的原型,因为每个对象都有一个constructor属性表示这个对象的构造函数:
①通过对象直接量创建的对象的constructor属性指向构造函数Object();
②通过new+构造函数创建的对象的constructor属性指向构造函数;
③通过Object.create()创建的对象的constructor属性指向与其原型对象的constructor属性指向相同;
要检测一个对象是否是另一个对象的原型(或处于原型链中),可以使用isPrototypeOf()方法。例如:
还有一个非标准但众多浏览器都已实现的对象的属性__proto__(同样是两个下划线开始和结束,以表明其为非标准),用以直接查询/设置对象的原型。
2.类属性
对象的类属性(class attribute)是一个字符串,用以表示对象的类型信息。ECMAScript 3 和ECMAScript 5 都未提供设置这个属性的方法,并只有一种间接的方法可以查询它。默认的toString()方法(继承自Object.prototype)返回了这种格 式的字符串:[object class] 。因此,要想获得对象的类,可以调用对象的toString()方法,然后提取已返回字符串的第8到倒数第二个位置之间的字符。不过,很多对象继承的 toString()方法重写了(比如:Array、Date等),为了能调用正确的toString()版本,必须间接地调用 Function.call()方法。下面代码可以返回传递给它的任意对象的类:
function classof(obj){ if(o === null){ return 'Null'; } if(o === undefined){ return 'Undefined'; } return Object.prototype.toString.call(o).slice(8, -1); }
classof()函数可以传入任何类型的参数。下面是使用实例:
总结:从运行结果可以看出通过三种方式创建的对象的类属性都是'Object'。
3.可扩展性
对象的可扩展性用以表示是否可以给对象添加新属性。所有内置对象和自定义对象都是显示可扩展的(除非将它们转换为不可扩展),宿主对象的可扩展性是由JavaScript引擎定义的。ECMAScript 5中定义了用来查询和设置对象可扩展性的函数:
①(查询)通过将对象传入Object.isExtensible(),来判断该对象是否是可扩展的。
②(设置)如果想将对象转换为不可扩展,需要调用Object.preventExtensions(),将待转换的对象作为参数传进去。注意:
a.一旦将对象转换为不可扩展的,就无法再将其转换回可扩展的了;
b.preventExtensions()只影响到对象本身的可扩展性,如果给一个不可扩展的对象的原型添加属性,这个不可扩展的对象同样会继承这些新属性;
进一步,Object.seal()和Object.preventExtensions()类似,除了能将对象设置为不可扩展的,还可以将对象的 所有自有属性都设置为不可配置的。对于那些已经封闭(sealed)起来的对象是不能解封的。可以使用Object.isSealed()来检测对象是否 封闭。
更进一步,Object.freeze()将更严格地锁定对象——“冻结”(frozen)。除了将对象设置为不可扩展和将其属性设置为不可配置之 外,还可以将它自有的所有数据属性设置为只读(若对象的存取器属性有setter方法,存取器属性将不受影响,仍可通过给属性赋值调用它们)。使用 Object.isFrozen()来检测对象是否总结。
总结:Object.preventExtensions()、Object.seal()和Object.freeze()都返回传入的对象,也就是说,可以通过嵌套的方式调用它们:
var obj = Object.seal(Object.create(Object.freeze({x:1}),{y:{value: 2, writable: true}));
这条语句中使用Object.create()函数传入了两个参数,即第一个参数是创建出的对象的原型对象,第二个参数是在创建对象是直接给其定义的属性,并且附带定义了属性的特性。
十.对象的序列化
前面说完了对象的属性以及对象属性的特性,东西还是蛮多的,不知道你是否已看晕。不过,下面就是比较轻松的话题了!