判定JS的对象类型基本是MISSION Impossible。
JS的对象可能是JS核心对象、可能是自定义类、可能是空等等,但是其弱类型机制又无法有什么很准确的方法来判定这个对象到底是什么,特别是当这个东西是有继承的……
引用
typeof is useful primarily for distinguishing primitive types from objects. There are a few quirks to typeof. First, remember that typeof null is "object", while typeof undefined is "undefined". Also, the type of any array is "object" because all arrays are objects. However, the type of any function is "function", even though functions are objects, too.
typeof运算符是JS中主要的判定方式,但它很怪癖:
typeof null // Yields "obejct"
typeof undefined // yields "undefined"
typeof array_var // array_var represents an array variable; yields "object"
typeof function_var // function_var represents an function variable; yields "function"
再接着就是instanceof了
x instanceof Array
引用
The left side of instanceof is the value to be tested, and the right side should be a constructor function that defines a class.
上面这个语句中,JS会测试这句话的左值,右值是一个构造函数;任何这个类的实例或这个类父类的实例都会返回ture
假设f是一个Function,以下表达式都是ture
typeof f == "function"
f instanceof Function
f instanceof Object
引用
If you want to test whether an object is an instance of one specific class and not an instance of some subclass, you can check its constructor property.
如果你想确定一个对象是一个确定类的实例,而不是其子类的实例,你必须比较这两个对象的构造函数:
var d = new Date( ); // A Date object; Date extends Object
var isobject = d instanceof Object; // evaluates to true
var realobject = d.constructor==Object; // evaluates to false
Object.toString( ) for Object Typing
百年不用的toString()方法
引用
A useful trick that uses the default implementation of the Object.toString( ) method can help in this case.
An interesting feature of the default toString( ) method is that it reveals some internal type information about built-in objects. The ECMAScript specification requires that this default toString( ) method always returns a string of the form:
[object
class]
class is the internal type of the object and usually corresponds to the name of the constructor function for the object.
arrays have a class of "Array", functions have a class of "Function", and Date objects have a class of "Date". The built-in Math object has a class of "Math", and all Error objects (including instances of the various Error subclasses) have a class of "Error". Client-side JavaScript objects and any other objects defined by the JavaScript implementation have an implementation-defined class (such as "Window", "Document", or "Form").
Objects of user-defined types, such as the Circle and Complex classes defined earlier in this chapter, always have a class of "Object", however, so this toString( ) technique is useful only for built-in object types.
Object默认的toString()方法,根据ECMAScript的标准,会返回一些必要的信息,格式如下:
[object
class]
class是一个对象的内部类型,通常是其构造函数的名字。
数组对象的class值为“Array”;函数对象的class值为“Function”;日期对象Date的class值为“Date”;Math对象的class值为“Math”;Error(包括其任何子类)对象的class值为“Error”。
而客户端对象都有相应的class值,像Window、Document、Form等等。
用户自定义对象,只有一个“Object”的class值,所以toString()其实也只对内建对象有效。
下面根据以上思想,编写一个增强型的类型判断函数:
function getType(x) {
// If x is null, return "null"
// x是null,返回“null”
if (x == null) return "null";
// Next try the typeof operator
// 先用基础的typeof判定
var t = typeof x;
// If the result is not vague, return it
if (t != "object") return t;
// Otherwise, x is an object. Use the default toString( ) method to
// get the class value of the object.
// 对于object对象,typeof无能为力,我们来找找对象的class值
var c = Object.prototype.toString.apply(x); // Returns "[object class]"
c = c.substring(8, c.length-1); // Strip off "[object" and "]"
// If the class is not a vague one, return it.
// 如果有具体的class值,而不是单纯的“object"
if (c != "Object") return c;
// If we get here, c is "Object". Check to see if
// the value x is really just a generic object.
// 函数运行到这里,那么该对象就是一个Object
if (x.constructor == Object) return c; // Okay the type really is "Object"
// For user-defined classes, look for a string-valued property named
// classname, that is inherited from the object's prototype
// 也有可能是自定义类,我们找一下它的构造函数中是否定义了classname这个属性
if ("classname" in x.constructor.prototype && // inherits classname
typeof x.constructor.prototype.classname == "string") // its a string
return x.constructor.prototype.classname;
// If we really can't figure it out, say so.
return "<unknown type>";
}