在【09类和模块】——2类和构造函数 中我们说过可以使用instanceof运算符和constructor属性来检测对象所属的类,但是使用instanceof运算符和constructor属性来检测对象所属的类有一个主要的问题,在多个执行上下文中存在构造函数的多个副本的时候,这两种方法的检测结果就会出错。多个执行上下文中的函数看起来一模一样,但是他们是相互独立的个体对象,因此彼此也不想等。
一种可能的解决方案是使用构造函数的名字而不是构造函数本身作为类的标识符。比如一个窗口里面的Array构造函数和另外一个窗口中的Array构造函数是不相等的,但是它们的名字是一样的。在一些javascript的实现中为函数对象提供了一个非标准的属性name,用来表示函数的名称。
下面我就定义一个type()函数以字符串的形式返回对象的类型。它使用typeof运算符来处理原始值和函数。对于对象来说,它要么返回class属性的值要么返回构造函数的名字
这里我先定义一个classof()函数,用于返回对象的类
function classof(o) {
return Object.prototype.toString.call(o).slice(8,-1);
};
再在Function类中添加一个getName()方法,用于返回函数的名字,不是函数的话返回null
Function.prototype.getName = function() {
if ("name" in this) return this.name;
return this.name = this.toString().match(/function\s*([^(]*)\(/)[1];
};
下面是可以判断值得类型的type()函数
// 如果o是null,返回null,如果o是NaN,返回nan
// 如果typeof所返回idea值不是“object”,则返回这个值
// 如果o的类不是“Object”,则返回这个值
// 如果o包含构造函数并且这个构造函数具有名称,则返回名称
// 否则,一律返回“Object”
function type(o){
var t,c,n //type,class,name
if(o === null) return "null";
if(o !== o) return "nan";
if((t = typeof(o)) !== "object") return t;
if((c = classof(o)) !== "Object") return c;
if (o.constructor && typeof(o.constructor) === "function" &&
(n = o.constructor.getName())) return n;
return "Object";
}