我们可以使用以下方法:
typeof
instanceof
object.prototype.toString
他们之间有什么大不同?
为什么你不能在不同的窗口或iframe
中使用'instanceof'进行检测?
答案 0 :(得分:5)
为什么你不能使用'instanceof'来检测不同的窗口或 iframe中
instanceof
检查原型链中是否包含给定的构造函数。不同的窗口/框架具有不同的构造函数实例,因此一个窗口/框架的构造函数与另一个窗口/框架的构造函数不匹配,因此instanceof
将不匹配它们。
至于使用哪种方法,它实际上取决于具体情况以及您试图辨别哪些类型的事物。
<强> typeof运算强>
对于辨别两种类型的对象,typeof
可能是最不实用的,因为所有内容都会被报告为对象。
<强>的instanceof 强>
只要不涉及来自单独窗口/框架的对象, instanceof
通常很有用。
<强>的toString 强>
Object.prototype.toString()
可用于辨别某些类型的对象(如Array和常规Javascript对象)之间的差异,但通常无法帮助您使用自定义对象。例如,您可以测试对象是否是这样的数组:
function isArray(obj) {
return Object.prototype.toString.call(obj) === '[object Array];
}
显然,较新的浏览器有Array.isArray()
提供此功能,但我在上面列举了使用Object.prototype.tostring()
的示例。
构造强>
constructor
属性实际上只是instanceof
的灵活性较低的版本。它只检查叶子构造函数(不是任何父构造函数),它具有与instanceof相同的多窗口/框架问题。最重要的是,并非所有代码都正确设置了constructor
属性。当我想制作一个特定对象的副本时,我偶尔会使用.constructor
属性,该对象是已知支持特定类型构造函数的一组对象之一,但我没有将它用于任何东西否则,甚至不会考虑将它用于对象类型检查。
鸭子打字
我发现“鸭子打字”是更强大的工具之一。在鸭子打字中(如果它像鸭子一样走路和说话,它必须是鸭子),你只需要测试你的对象是否具有你想要使用的属性和方法。如果是这样,它必须是兼容的对象,以便您可以使用它们。这样做的好处是,任何支持正确属性和方法的对象都可以使用您的代码,而且不需要特定的实现。
例如:
// if object supports printing, then print it
if (obj.print) {
obj.print();
}
注意这比检查此对象是否是已知支持打印的几种类型之一更通用。在这种情况下,print
方法的存在或缺乏告诉整个故事代码。您可以在不修改此代码的情况下添加支持或不支持打印的新对象类型。
<强>多态性强>
无论何时检查物体的类型,都值得问自己是否应该重新思考如何做事。你真的不想编写代码来检查什么类型的对象是什么,然后基于它的分支行为,如果它可以避免。相反,您宁愿在每个对象上调用一个公共方法,让对象决定哪种行为对于实现该方法很重要。
这方面的一个典型示例是,您只需在每个对象上实现.draw()
方法,而某些顶级代码只能在任何一组对象上调用.draw()
,而不知道该类型的内容对象是。这种多态性使得对象的类型与调用代码无关。它只是告诉每个对象执行一个任务,并将其留给给定对象的实现来执行适合该任务的任务。
答案 1 :(得分:0)
ECMA 6中另一个方便的方法是通过构造函数属性检测类型。这个脚本我已经在Node JS中使用了很多次:)。如果getFuncNames
参数为真,它甚至会找到函数的名称
// custom type
function MyType(){
}
var myType = new MyType();
// primitives
var array = [], obj = {}, str = "", date = new Date(),
num = 1, flt = 1.0, reg = new RegExp(/woohoo/g),
bool = true, udf = undefined, nul = null;
// names of various types (primitive and not)
var names = cName(array) + ", " + cName(obj) + ", " + cName(str) + ", " +
cName(num) + ", " + cName(flt) + ", " + cName(reg) + ", " +
cName(bool) + ", " + cName(date) + ", " + cName(myType) + ", " +
cName(MyType) + ", " + cName(udf) + ", " + cName(nul);
console.log( names );
// output: Array, Object, String, Number, Number, RegExp, Boolean, Date, MyType, MyType, undefined, null
// implementation
function cName(obj, getFuncNames){
// default to non-null value.
var ret = '';
if(typeof obj === 'undefined') { ret = 'undefined'; }
else if(obj === null) { ret = String(obj); }
else if(typeof obj.constructor !== 'undefined' && obj.constructor !== null){
ret = obj.constructor.name
if(ret == 'Function' && getFuncNames !== false) { ret = obj.name; }
}
return ret;
}