在我的特殊情况下:
callback instanceof Function
or
typeof callback == "function"
这有关系吗,有什么区别?
额外的资源:
花园typeof vs instanceof
在我的特殊情况下:
callback instanceof Function
or
typeof callback == "function"
这有关系吗,有什么区别?
额外的资源:
花园typeof vs instanceof
当前回答
这只是对这里所有其他解释的补充知识——我不建议在所有地方都使用.constructor。
TL;DR:在typeof不是一个选项的情况下,并且当你知道你不关心原型链的时候,Object.prototype.constructor可以是一个可行的甚至比instanceof更好的选择:
x instanceof Y
x.constructor === Y
它从1.1开始就在标准中了,所以不用担心向后兼容性。
Muhammad Umer也在这里的一个评论中简要地提到了这一点。它适用于所有有原型的东西——所以所有不是null或未定义的东西:
// (null).constructor; // TypeError: null has no properties
// (undefined).constructor; // TypeError: undefined has no properties
(1).constructor; // function Number
''.constructor; // function String
([]).constructor; // function Array
(new Uint8Array(0)).constructor; // function Uint8Array
false.constructor; // function Boolean()
true.constructor; // function Boolean()
(Symbol('foo')).constructor; // function Symbol()
// Symbols work, just remember that this is not an actual constructor:
// new Symbol('foo'); //TypeError: Symbol is not a constructor
Array.prototype === window.frames.Array; // false
Array.constructor === window.frames.Array.constructor; // true
此外,根据您的用例,它可能比instanceof快得多(原因可能是它不需要检查整个原型链)。在我的情况下,我需要一个快速的方法来检查一个值是否是一个类型数组:
function isTypedArrayConstructor(obj) {
switch (obj && obj.constructor){
case Uint8Array:
case Float32Array:
case Uint16Array:
case Uint32Array:
case Int32Array:
case Float64Array:
case Int8Array:
case Uint8ClampedArray:
case Int16Array:
return true;
default:
return false;
}
}
function isTypedArrayInstanceOf(obj) {
return obj instanceof Uint8Array ||
obj instanceof Float32Array ||
obj instanceof Uint16Array ||
obj instanceof Uint32Array ||
obj instanceof Int32Array ||
obj instanceof Float64Array ||
obj instanceof Int8Array ||
obj instanceof Uint8ClampedArray ||
obj instanceof Int16Array;
}
https://run.perf.zone/view/isTypedArray-constructor-vs-instanceof-1519140393812
结果是:
Chrome 64.0.3282.167(64位,Windows)
Firefox 59.0b10(64位,Windows)
出于好奇,我针对typeof做了一个快速的玩具基准测试;令人惊讶的是,它的表现并没有差到哪里去,而且在Chrome中似乎还要快一点:
let s = 0,
n = 0;
function typeofSwitch(t) {
switch (typeof t) {
case "string":
return ++s;
case "number":
return ++n;
default:
return 0;
}
}
// note: no test for null or undefined here
function constructorSwitch(t) {
switch (t.constructor) {
case String:
return ++s;
case Number:
return ++n;
default:
return 0;
}
}
let vals = [];
for (let i = 0; i < 1000000; i++) {
vals.push(Math.random() <= 0.5 ? 0 : 'A');
}
https://run.perf.zone/view/typeof-vs-constructor-string-or-number-1519142623570
注意:函数列表的顺序在图像之间切换!
Chrome 64.0.3282.167(64位,Windows)
Firefox 59.0b10(64位,Windows)
注意:函数列表的顺序在图像之间切换!
其他回答
我认为,当callback是Function的子类型时,instanceof也可以工作
使用typeof的一个很好的理由是变量可能是未定义的。
alert(typeof undefinedVariable); // alerts the string "undefined"
alert(undefinedVariable instanceof Object); // throws an exception
使用instanceof的一个很好的理由是变量可能为空。
var myNullVar = null;
alert(typeof myNullVar ); // alerts the string "object"
alert(myNullVar instanceof Object); // alerts "false"
所以在我看来,这取决于你在检查什么类型的数据。
为了把事情弄清楚,你需要知道两个事实:
instanceof操作符测试构造函数的prototype属性是否出现在对象的prototype链中的任何位置。在大多数情况下,这意味着对象是通过使用该构造函数或其后代构造函数创建的。但prototype也可以通过Object.setPrototypeOf()方法(ECMAScript 2015)或__proto__属性显式设置(旧浏览器,已弃用)。但是,由于性能问题,不建议更改对象的原型。
因此,instanceof仅适用于对象。在大多数情况下,你不会使用构造函数来创建字符串或数字。你可以。但你几乎从来没有这样做过。
instanceof也不能检查使用哪个构造函数创建对象,但返回true,即使对象是从被检查的类派生的。在大多数情况下,这是理想的行为,但有时并非如此。所以你要保持这种心态。
另一个问题是不同的作用域具有不同的执行环境。这意味着它们有不同的内置(不同的全局对象,不同的构造函数,等等)。这可能会导致意想不到的结果。
例如,[]instanceof window.frames[0].Array将返回false,因为Array。== window.frames[0]. array和数组继承自前者。 此外,它不能用于未定义的值,因为它没有原型。
The typeof operator tests whether value belong to one of six basic types: "number", "string", "boolean", "object", "function" or "undefined". Where the string "object" belong all objects (except functions, which are objects, but have its own value in typeof operator), and also "null" value and arrays (for "null" it's a bug, but this bug is so old, so it's become a standard). It doesn't rely on constructors and can be used even if value is undefined. But it's doesn't give any details about objects. So if you needed it, go to instanceof.
现在我们来讨论一个棘手的问题。如果使用构造函数创建基元类型呢?
let num = new Number(5);
console.log(num instanceof Number); // print true
console.log(typeof num); // print object
num++; //num is object right now but still can be handled as number
//and after that:
console.log(num instanceof Number); // print false
console.log(typeof num); // print number
就像魔法一样。但事实并非如此。这就是所谓的装箱(按对象包装原语值)和解装箱(从对象中提取包装的原语值)。这样的代码似乎“有点”脆弱。当然,您可以避免使用构造函数创建原始类型。但还有另一种可能的情况,拳击可能会打到你。在原语类型上使用Function.call()或Function.apply()时。
function test(){
console.log(typeof this);
}
test.apply(5);
为了避免这种情况,你可以使用严格模式:
function test(){
'use strict';
console.log(typeof this);
}
test.apply(5);
乌利希期刊指南: 自ECMAScript 2015以来,又增加了一种名为Symbol的类型,它有自己的typeof == " Symbol "。
console.log(typeof Symbol());
// expected output: "symbol"
你可以在MDN上阅读它:(Symbol, typeof)。
没有必要用上面的大量例子来压倒你,只需要记住两个观点:
typeof var; is an unary operator will return the original type or root type of var. so that it will return primitive types(string, number, bigint, boolean, undefined, and symbol) or object type. in case of higher-level object, like built-in objects (String, Number, Boolean, Array..) or complex or custom objects, all of them is object root type, but instance type built base on them is vary(like OOP class inheritance concept), here a instanceof A - a binary operator - will help you, it will go through the prototype chain to check whether constructor of the right operand(A) appears or not.
所以当你想检查“根类型”或使用基元变量时,使用“typeof”,否则使用“instanceof”。
Null是一种特殊情况,它看起来很原始,但实际上是object的特殊情况。使用a === null代替检查null。
另一方面,function也是一种特殊情况,它是内置对象,但typeof返回函数
正如你所看到的,instanceof必须遍历原型链,而typeof只检查根类型一次,所以很容易理解为什么typeof比instanceof快
instanceof将不适用于原语,例如"foo" instanceof String将返回false,而typeof "foo" == " String "将返回true。
另一方面,当涉及到自定义对象(或类,无论你想叫它们什么)时,typeof可能不会做你想做的事情。例如:
function Dog() {}
var obj = new Dog;
typeof obj == 'Dog' // false, typeof obj is actually "object"
obj instanceof Dog // true, what we want in this case
函数碰巧既是“函数”原语,又是“函数”的实例,这有点奇怪,因为它不像其他原语类型那样工作,例如。
(typeof function(){} == 'function') == (function(){} instanceof Function)
but
(typeof 'foo' == 'string') != ('foo' instanceof String)