深入探究JavaScript对象系列(四)
前两篇主要是写了关于JavaScript对象中属性的特性,在这篇中让我们来看看对象的属性,对象共有3个比较重要的与之相关的属性,分别是原型、类、可扩展性。
一.原型属性
原型这个概念已经在第一篇中解释过了,它是JavaScript对象继承的核心。对象的原型属性是用来继承属性的,它在对象创建指出就被设置好了,回想下第一篇中介绍的创建对象的3种方法,第一种通过对象直接量创建的对象使用Object.prototype作为它的原型,其实等价于使用Object()这个构造函数来创建对象;第二种通过new和构造函数创建的对象使用构造函数的prototype属性作为它的原型;第三种通过Object.create()方法创建的对象使用方法的第一个参数作为它的原型。
在ECMAScript5中提供了Object.getPrototypeOf()方法来查询它的原型,如下:
1 var o = {}; 2 Object.getPrototypeOf(o); 3 //返回 Object {} 4 5 var d = new Date(); 6 Object.getPrototypeOf(d); 7 //返回 Invalid Date 8 9 var o = {x:1, y:2}; 10 var i = Object.create(o); 11 Object.getPrototypeOf(i); 12 //返回Object {x: 1, y: 2}
要想检测一个对象是否是另一个对象的原型或处于原型链中,可以使用Object,isPrototypeOf()方法,实现的功能跟instanceof运算符类似,由于比较简单,例子还是不写了。
二.类属性
在JavaScript中,对象的类属性是一个类似于这样的字符串 [object classname],虽然js没有本身没有提供获取类属性的方法,但是大卫在这本书中给我们提供了一个间接方法来查询:根据toString()方法的返回值,然后提取字符串的第八个至倒数第二个位置之间的字符串。
由于很多对象继承的toString()方法在继承过程中被改变了,所以只能通过call()来调用原始的toString()方法,以下的例子就是通过这个方案来获取对象的类属性:
1 function classof(o){ 2 if(o === null) return "null"; 3 if(o === undefined) return "undefined"; 4 5 return Object.prototype.toString.call(o).slice(8,-1); 6 }
三.可扩展性
对象的可扩展性用以表示是否可以给对象添加新属性。所有JavaScript内置对象和自定义对象都是可显式扩展的,宿主对象的可扩展性是由运行环境定义的。需要注意的是,对象是否可扩展不会影响到该对象的原型对象的可扩展性,即同样会继承原型对象中新增的属性。
在ECMAScript5中定义了Object.isExtensible()方法来判断对象是否可以扩展,定义了Object.preventExtensions()方法来将一个可扩展的对象转为不可扩展,且是单向的,即转换后无法再转回来。
可扩展性的目的是将对象“锁定”,以避免外界的干扰,对象的可扩展性通常和该对象中属性的可写性和可配置型来配合使用,在ECMAScript5中也定义一组类似的方法来实现这个目的:Object.seal()方法和Object.isSealed()方法,前者除了能将对象设置为不可扩展的,还可以将对象的自有属性都设置为不可配置的,后者则用来检查对象是否被封闭(sealed)。同样的,被封闭的对象无法“解封”。
此外,JavaScript还提供了一组更严格的锁定对象的方法:Object.freeze()和Object.isFrozen(),前者不但把将对象设置为不可扩展的和将对象的自有属性都设置为不可配置,还可以将所有数据属性设置为只读(但不影响存取器属性的setter方法);后者则判断一个对象是否被frozen。
到了这里,基本上把js基于对象的基础知识写完了,提到了很多方法,看看哪天空的时候把这些方法单独拎出来再写下。