在我的特定情况下:
callback instanceof Function
或
typeof callback == "function"
甚至重要,有什么区别?
其他资源:
JavaScript-Garden typeof vs instanceof
答案 0 :(得分:472)
instanceof
:var ClassFirst = function () {};
var ClassSecond = function () {};
var instance = new ClassFirst();
typeof instance; // object
typeof instance == 'ClassFirst'; // false
instance instanceof Object; // true
instance instanceof ClassFirst; // true
instance instanceof ClassSecond; // false
typeof
:'example string' instanceof String; // false
typeof 'example string' == 'string'; // true
'example string' instanceof Object; // false
typeof 'example string' == 'object'; // false
true instanceof Boolean; // false
typeof true == 'boolean'; // true
99.99 instanceof Number; // false
typeof 99.99 == 'number'; // true
function() {} instanceof Function; // true
typeof function() {} == 'function'; // true
instanceof
:/regularexpression/ instanceof RegExp; // true
typeof /regularexpression/; // object
[] instanceof Array; // true
typeof []; //object
{} instanceof Object; // true
typeof {}; // object
最后一个有点棘手:
typeof null; // object
答案 1 :(得分:120)
两者在功能上都相似,因为它们都返回类型信息,但我个人更喜欢instanceof
因为它比较实际类型而不是字符串。类型比较不容易出现人为错误,并且技术上更快,因为它比较内存中的指针而不是进行整个字符串比较。
答案 2 :(得分:94)
使用typeof的一个很好的理由是变量可能未定义。
alert(typeof undefinedVariable); // alerts the string "undefined"
alert(undefinedVariable instanceof Object); // throws an exception
使用instanceof的一个很好的理由是变量可能为null。
var myNullVar = null;
alert(typeof myNullVar ); // alerts the string "object"
alert(myNullVar instanceof Object); // alerts "false"
所以我认为这取决于您正在检查的数据类型。
答案 3 :(得分:26)
为了说清楚,你需要知道两个事实:
Object.setPrototypeOf()
方法(ECMAScript 2015)或__proto__
属性(旧浏览器,不推荐使用)明确设置原型。但是,由于性能问题,不建议更改对象的原型。 因此instanceof仅适用于对象。在大多数情况下,您不使用构造函数来创建字符串或数字。您可以。但你几乎从不这样做。
instanceof也无法检查,确切地使用了哪个构造函数来创建对象,但是返回true,即使object是从被检查的类派生的。在大多数情况下,这是期望的行为,但有时并非如此。所以你需要保持这种想法。
另一个问题是不同的范围具有不同的执行环境。这意味着它们具有不同的内置函数(不同的全局对象,不同的构造函数等)。这可能会导致意外结果。
例如,[] instanceof window.frames[0].Array
将返回false
,因为Array.prototype !== window.frames[0].Array
和数组继承自前者。
此外,它不能用于未定义的值,因为它没有原型。
现在让我们谈谈一件棘手的事情。如果使用构造函数创建基本类型怎么办?
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);
<强> UPD:强> 自ECMAScript 2015以来,还有一种名为Symbol的类型,它有自己的typeof == “symbol”。
console.log(typeof Symbol());
// expected output: "symbol"
答案 4 :(得分:14)
我在Safari 5和Internet Explorer 9中发现了一些非常有趣(读作“可怕”)的行为。我在Chrome和Firefox中使用它非常成功。
if (typeof this === 'string') {
doStuffWith(this);
}
然后我在IE9中测试,它根本不起作用。大惊喜。但在Safari中,它是断断续续的!所以我开始调试,我发现Internet Explorer 总是返回false
。但最奇怪的是Safari似乎在其JavaScript VM中进行了某种优化,true
第一次时,false
每次你重新加载!
我的大脑几乎爆炸了。
所以现在我已经解决了这个问题:
if (this instanceof String || typeof this === 'string')
doStuffWith(this.toString());
}
现在一切都很好。请注意,您可以调用"a string".toString()
,它只返回字符串的副本,即
"a string".toString() === new String("a string").toString(); // true
所以从现在开始我都会使用它们。
答案 5 :(得分:7)
其他重大的实际差异:
// Boolean
var str3 = true ;
alert(str3);
alert(str3 instanceof Boolean); // false: expect true
alert(typeof str3 == "boolean" ); // true
// Number
var str4 = 100 ;
alert(str4);
alert(str4 instanceof Number); // false: expect true
alert(typeof str4 == "number" ); // true
答案 6 :(得分:7)
instanceof
是callback
的子类型时, Function
也有效,我认为
答案 7 :(得分:4)
instanceof
可能不稳定 - 我相信主要框架会试图避免使用它。不同的窗口是它可以破解的方式之一 - 我相信类层次结构也可能会混淆它。
有更好的方法可以测试对象是否是某种内置类型(通常是您想要的)。创建实用程序功能并使用它们:
function isFunction(obj) {
return typeof(obj) == "function";
}
function isArray(obj) {
return typeof(obj) == "object"
&& typeof(obj.length) == "number"
&& isFunction(obj.push);
}
等等。
答案 8 :(得分:3)
我建议使用原型callback.isFunction()
。
他们已经找出了差异,你可以依靠他们的理由。
我猜其他JS框架也有这样的东西。
我相信, instanceOf
无法在其他窗口中定义的函数上运行。
他们的功能与您的window.Function
不同。
答案 9 :(得分:3)
检查功能时,必须始终使用typeof
。
这就是区别:
var f = Object.create(Function);
console.log(f instanceof Function); //=> true
console.log(typeof f === 'function'); //=> false
f(); // throws TypeError: f is not a function
这就是为什么绝不能使用instanceof
来检查函数。
答案 10 :(得分:3)
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)
但
(typeof 'foo' == 'string') != ('foo' instanceof String)
答案 11 :(得分:2)
<强>性能强>
typeof
在两者都适用的情况下比instanceof
快。
根据您的引擎,typeof
支持的效果差异可能大约 20%。 (您的里程可能会有所不同)
以下是Array
的基准测试:
var subject = new Array();
var iterations = 10000000;
var goBenchmark = function(callback, iterations) {
var start = Date.now();
for (i=0; i < iterations; i++) { var foo = callback(); }
var end = Date.now();
var seconds = parseFloat((end-start)/1000).toFixed(2);
console.log(callback.name+" took: "+ seconds +" seconds.");
return seconds;
}
// Testing instanceof
var iot = goBenchmark(function instanceofTest(){
(subject instanceof Array);
}, iterations);
// Testing typeof
var tot = goBenchmark(function typeofTest(){
(typeof subject == "object");
}, iterations);
var r = new Array(iot,tot).sort();
console.log("Performance ratio is: "+ parseFloat(r[1]/r[0]).toFixed(3));
结果
instanceofTest took: 9.98 seconds.
typeofTest took: 8.33 seconds.
Performance ratio is: 1.198
答案 12 :(得分:2)
这只是对所有其他解释的补充知识 - 我不建议在任何地方使用.constructor
。
TL; DR:在typeof
不是选项的情况下, 当您知道自己不关心原型链时 ,Object.prototype.constructor
可以是instanceof
的可行或甚至更好的选择:
x instanceof Y
x.constructor === Y
自1.1以来它一直处于标准状态,所以不用担心向后兼容性。
Muhammad Umer在这里的评论中也简要地提到了这一点。它适用于所有原型 - 所以一切都不是null
或undefined
:
// (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)
注意:列出功能的顺序在图像之间切换!
答案 13 :(得分:2)
显着的实际差异:
var str = 'hello word';
str instanceof String // false
typeof str === 'string' // true
不要问我为什么。
答案 14 :(得分:1)
使用instanceof,因为如果更改类的名称,则会出现编译器错误。
答案 15 :(得分:1)
var newObj = new Object;//instance of Object
var newProp = "I'm xgqfrms!" //define property
var newFunc = function(name){//define function
var hello ="hello, "+ name +"!";
return hello;
}
newObj.info = newProp;// add property
newObj.func = newFunc;// add function
console.log(newObj.info);// call function
// I'm xgqfrms!
console.log(newObj.func("ET"));// call function
// hello, ET!
console.log(newObj instanceof Object);
//true
console.log(typeof(newObj));
//"object"
答案 16 :(得分:1)
无需过多考虑上述例子,只需记住以下两个观点:
typeof var;
是一元运算符,将返回var的原始类型或根类型。因此它将返回原始类型(string
,number
,bigint
,boolean
,undefined
和symbol
)或{{1} }类型。
对于高级对象(例如内置对象(String,Number,Boolean,Array ..)或复杂或自定义对象),它们都是object
根类型,但实例基于它们构建的类型是多种多样的(例如OOP类继承概念),这里的object
(一个二进制运算符)将为您提供帮助,它将遍历原型链以检查是否出现了正确操作数(A)的构造函数或不是。
因此,每当您要检查“根类型”或使用原始变量时,请使用“ typeof”,否则请使用“ instanceof”。
a instanceof A
是一个特例,看似原始,但实际上是对象的特例。使用null
来检查是否为空。
另一方面,a === null
也是一个特例,它是内置对象,但是function
返回typeof
您可以看到function
必须经过原型链,而instanceof
只需检查一次根类型,因此很容易理解为什么typeof
比typeof
更快
答案 17 :(得分:0)
尽管 instanceof 可能比 typeof 快一点,但我更喜欢第二种,因为这种可能的魔法:
function Class() {};
Class.prototype = Function;
var funcWannaBe = new Class;
console.log(funcWannaBe instanceof Function); //true
console.log(typeof funcWannaBe === "function"); //false
funcWannaBe(); //Uncaught TypeError: funcWannaBe is not a function
答案 18 :(得分:0)
还有一种情况是,您只能与instanceof
进行整理 - 它返回true或false。使用typeof
,您可以获得某种
答案 19 :(得分:0)
考虑到性能,您最好使用typeof 使用典型硬件,如果您创建一个循环为1000万次迭代的脚本 指令:typeof str ==&#39; string&#39;将需要9毫秒 而&#39;字符串&#39; instanceof String需要19ms
答案 20 :(得分:0)
当然重要........!
让我们通过示例来解决这个问题。在我们的示例中,我们将以两种不同的方式声明函数。
我们将同时使用 function declaration
和 Function Constructor 。我们将了解 typeof
和 instanceof
在这两种不同情况下的表现。
使用函数声明创建函数:
function MyFunc(){ }
typeof Myfunc == 'function' // true
MyFunc instanceof Function // false
这种不同结果的可能解释是,正如我们做了一个函数声明, typeof
可以理解它是一个函数。因为 typeof
检查是否操作了typeof的表达式,在我们的例子中 MyFunc
已实现 Call Method 。如果它实现了 Call
方法,那么它就是一个函数。否则不会。为了澄清检查 ecmascript specification for typeof 。
使用函数构造函数创建函数:
var MyFunc2 = new Function('a','b','return a+b') // A function constructor is used
typeof MyFunc2 == 'function' // true
MyFunc2 instanceof Function // true
此处 typeof
断言 MyFunc2
是一个函数以及 instanceof
运算符。我们已经知道 typeof
检查 MyFunc2
是否实施了 Call
方法。作为 MyFunc2
是一个函数,它实现了 call
方法, typeof
知道它是一个函数。另一方面,我们使用 function constructor
创建 MyFunc2
,它成为 Function constructor
。这就是 instanceof
也解析为 true
的原因。
使用什么更安全?
正如我们在两种情况下都可以看到 typeof
运算符可以成功断言我们在这里处理函数,它比 instanceof
。如果 instanceof
, function declaration
会失败,因为 function declarations
不是的实例Function constructor
强>
最佳做法:
建议 Gary Rafferty 时,最佳方法应该是同时使用typeof和instanceof。
function isFunction(functionItem) {
return typeof(functionItem) == 'function' || functionItem instanceof Function;
}
isFunction(MyFunc) // invoke it by passing our test function as parameter
答案 21 :(得分:0)
来自严格的OO培养,我会去
callback instanceof Function
字符串很容易出现我的拼写错误或其他拼写错误。另外我觉得它看起来更好。
答案 22 :(得分:0)
非常准确 instanceof 应该用于通过构造函数(通常是自定义类型)创建值的地方,例如
var d = new String("abc")
typeof 可以检查仅由赋值创建的值,例如
var d = "abc"
答案 23 :(得分:0)
typeof:根据 MDN 文档,typeof 是一个一元运算符,它返回一个字符串,指示未计算的操作数的类型。
在字符串原始数据和字符串对象的情况下,typeof 返回以下内容:
const toUpdate = {
...
[key]: value
}
or
toUpdate[key] = value;
or
toUpdate[`${key}`] = value;
any of the above works
instanceof:是一个二元运算符,接受一个对象和一个构造函数。 它返回一个布尔值,指示对象在其原型链中是否具有给定的构造函数。
当应用于上面的字符串实例时,与字符串相比,它的行为如下:
const a = "I'm a string primitive";
const b = new String("I'm a String Object");
typeof a; --> returns 'string'
typeof b; --> returns 'object'
参考:https://bambielli.com/til/2017-06-18-typeof-vs-instanceof/
答案 24 :(得分:-1)
根据MDN documentation about typeof,用“ new”关键字实例化的对象的类型为“ object”:
typeof 'bla' === 'string';
// The following are confusing, dangerous, and wasteful. Avoid them.
typeof new Boolean(true) === 'object';
typeof new Number(1) === 'object';
typeof new String('abc') === 'object';
documentation about instanceof指出:
const objectString = new String('String created with constructor');
objectString instanceOf String; // returns true
objectString instanceOf Object; // returns true
因此,如果您想检查例如无论什么东西都是字符串,最安全的方法是使用instanceof
。