在我的特殊情况下:
callback instanceof Function
or
typeof callback == "function"
这有关系吗,有什么区别?
额外的资源:
花园typeof vs instanceof
在我的特殊情况下:
callback instanceof Function
or
typeof callback == "function"
这有关系吗,有什么区别?
额外的资源:
花园typeof vs instanceof
两者在功能上相似,因为它们都返回类型信息,但我个人更喜欢instanceof,因为它比较的是实际类型而不是字符串。类型比较不容易出现人为错误,而且技术上更快,因为它比较内存中的指针,而不是整个字符串的比较。
我建议使用原型的callback.isFunction()。
他们已经找出了其中的区别,你可以相信他们的理由。
我猜其他JS框架也有这样的东西。
instanceOf不会在其他窗口中定义的函数上工作,我相信。 它们的函数和你的窗口函数不同。
instanceof在Javascript中是不可靠的——我相信主流框架都尽量避免使用它。不同的窗口是它可以打破的方式之一-我相信职业层次结构也可以混淆它。
有更好的方法来测试对象是否为某种内置类型(通常是您想要的类型)。创建实用函数并使用它们:
function isFunction(obj) {
return typeof(obj) == "function";
}
function isArray(obj) {
return typeof(obj) == "object"
&& typeof(obj.length) == "number"
&& isFunction(obj.push);
}
等等。
使用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"
所以在我看来,这取决于你在检查什么类型的数据。
显著的实际差异:
var str = 'hello word';
str instanceof String // false
typeof str === 'string' // true
别问我为什么。
其他重要的实际差异:
// 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
使用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
我在Safari 5和Internet Explorer 9中发现了一些非常有趣的(读作“可怕的”)行为。我在Chrome和Firefox中成功地使用了这个功能。
if (typeof this === 'string') {
doStuffWith(this);
}
然后我在IE9中测试,它根本不能工作。大惊喜。但在Safari中,它是间歇性的!我开始调试,发现ie总是返回false。但最奇怪的是,Safari似乎在它的JavaScript VM中做了某种优化,第一次为真,但每次点击重载时为假!
我的大脑几乎爆炸了。
所以现在我决定这样做:
if (this instanceof String || typeof this === 'string')
doStuffWith(this.toString());
}
现在一切都很好。请注意,你可以调用"a string". tostring(),它只是返回字符串的副本,即。
"a string".toString() === new String("a string").toString(); // true
所以从现在开始我将两者都用。
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)
性能
在两者都适用的情况下,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
为了把事情弄清楚,你需要知道两个事实:
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)。
尽管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
当检查一个函数时,必须总是使用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来检查函数。
var newObj = new Object;//对象实例 var newProp = "I'm xgqfrms!"/ /定义属性 var newFunc = function(name){//定义函数 Var hello ="hello, "+ name +"!"; 返回你好; } //添加属性newObj.info = newProp newObj。//添加函数 console.log(newObj.info) //我是xgqfrms! console.log(newObj.func("ET")) //你好,ET! console.log(newObj instanceof Object); / /正确的 console.log (typeof (newObj)); / /“对象”
考虑到性能,您最好使用typeof 对于典型的硬件,如果您创建一个具有1000万次迭代循环的脚本 指令:typeof STR == 'string'将花费9毫秒 而'string' instanceof string将花费19毫秒
当然这很重要........!
让我们用例子来解释一下。在我们的例子中,我们将以两种不同的方式声明函数。
我们将同时使用函数声明和函数构造函数。我们将了解typeof和instanceof在这两种不同场景中的行为。
使用函数声明创建函数:
function MyFunc(){ }
typeof Myfunc == 'function' // true
MyFunc instanceof Function // false
对于这种不同的结果,可能的解释是,因为我们做了一个函数声明,typeof可以理解它是一个函数。因为typeof检查typeof的表达式是否被操作,在我们的例子中,MyFunc是否实现了Call Method。如果它实现了Call方法,它就是一个函数。为了澄清,请检查ecmascript的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是一个函数,它实现了调用方法,这就是typeof如何知道它是一个函数。另一方面,我们使用函数构造函数来创建MyFunc2,它成为函数构造函数的一个实例。这就是为什么instanceof也解析为true。
用什么更安全?
我们可以看到,在这两种情况下,typeof操作符都可以成功地断言我们在处理一个函数,它比instanceof更安全。instanceof在函数声明的情况下将失败,因为函数声明不是function构造函数的实例。
最佳实践:
正如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
这只是对这里所有其他解释的补充知识——我不建议在所有地方都使用.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)
注意:函数列表的顺序在图像之间切换!
准确地说 应该在通过构造函数(通常是自定义类型)创建值的地方使用Instanceof。
var d = new String("abc")
而typeof用于检查仅由赋值创建的值,例如
var d = "abc"
没有必要用上面的大量例子来压倒你,只需要记住两个观点:
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快
根据MDN关于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';
而关于instanceof点的文档说明:
const objectString = new String('String created with constructor');
objectString instanceOf String; // returns true
objectString instanceOf Object; // returns true
因此,如果有人想检查,例如,某东西是一个字符串,无论它是如何创建的,最安全的方法是使用instanceof。
typeof:根据MDN文档,typeof是一个一元操作符,返回指示未求值操作数类型的字符串。
在字符串原语和字符串对象的情况下,typeof返回如下:
const a = "I'm a string primitive";
const b = new String("I'm a String Object");
typeof a; --> returns 'string'
typeof b; --> returns 'object'
Instanceof:是一个二进制操作符,接受一个对象和一个构造函数。它返回一个布尔值,指示对象的原型链中是否有给定的构造函数。
当应用于上面的string实例时,并与string进行比较,它的行为如下:
const a = "I'm a string primitive";
const b = new String("I'm a String Object");
a instanceof String; --> returns false
b instanceof String; --> returns true
参考:https://bambielli.com/til/2017-06-18-typeof-vs-instanceof/