在我的情况下:
callback instanceof Function
要么
typeof callback == "function"
甚至有关系吗,有什么区别?
附加资源:
JavaScript-花园typeof与instanceof
Object.prototype.toString
ecma-international.org/ecma-262/6.0/…
.constructor
属性即可。
在我的情况下:
callback instanceof Function
要么
typeof callback == "function"
甚至有关系吗,有什么区别?
附加资源:
JavaScript-花园typeof与instanceof
Object.prototype.toString
ecma-international.org/ecma-262/6.0/…
.constructor
属性即可。
Answers:
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
Use instanceof for complex built in types
-这仍然容易出错。最好使用ES5 Array.isArray()
等。或建议的垫片。
两者在功能上相似,因为它们都返回类型信息,但是我个人更喜欢instanceof
因为它是在比较实际类型而不是字符串。类型比较不容易发生人为错误,并且从技术上讲它更快,因为它比较内存中的指针而不是进行整个字符串比较。
使用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"
因此,我认为这实际上取决于您要检查的数据类型。
instanceof
不能与基本类型进行比较,typeof可以。
undefined instanceof Object
返回false,并且不会引发异常。我不知道这种变化是最近发生的,但是它instanceof
更具吸引力。
undefined instanceof Object
不会因为undefined
定义了eh而引发异常。该常量存在于名称空间中。当变量不存在时(例如由于输入错误),instanceof将引发异常。另一方面,在不存在的变量上使用typeof会产生“未定义”。
为了弄清楚,您需要知道两个事实:
Object.setPrototypeOf()
方法(ECMAScript 2015)或__proto__
属性(旧的浏览器,已弃用)显式设置。但是由于性能问题,不建议更改对象的原型。 因此instanceof仅适用于对象。在大多数情况下,您不会使用构造函数来创建字符串或数字。您可以。但是你几乎从不这样做。
同样instanceof无法检查,确切地使用了哪个构造函数创建对象,但是即使对象是从要检查的类派生的,也会返回true。在大多数情况下,这是所需的行为,但有时并非如此。因此,您需要保持头脑。
另一个问题是,不同的作用域具有不同的执行环境。这意味着它们具有不同的内置函数(不同的全局对象,不同的构造函数等)。这可能会导致意外结果。
例如,[] 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"
if an object is created by a given constructor
这是不正确的。 o instanceof C
如果o从C.prototype继承,将返回true。您稍后在回答中提到了一些有关此内容的信息,但不是很清楚。
我已经在Safari 5和Internet Explorer 9中发现了一些非常有趣(称为“可怕”)的行为。我在Chrome和Firefox中成功使用了此行为。
if (typeof this === 'string') {
doStuffWith(this);
}
然后,我在IE9中进行了测试,但它根本不起作用。大惊喜。但是在Safari中,它是断断续续的!因此,我开始调试,发现Internet Explorer 总是在返回false
。但最奇怪的是,Safari浏览器似乎是在做某种在它的JavaScript虚拟机优化的地方是true
在第一时间,但false
每一次你打重装!
我的大脑快要爆炸了。
所以现在我已经解决了:
if (this instanceof String || typeof this === 'string')
doStuffWith(this.toString());
}
现在一切正常。注意,您可以调用"a string".toString()
,它只返回字符串的副本,即
"a string".toString() === new String("a string").toString(); // 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
Javascript中的代码可能会出现问题-我相信主要框架会尽量避免使用它。不同的窗口是打破窗口的方式之一-我相信类层次结构也可能使窗口混淆。
有更好的方法来测试对象是否为某种内置类型(通常是您想要的)。创建实用程序函数并使用它们:
function isFunction(obj) {
return typeof(obj) == "function";
}
function isArray(obj) {
return typeof(obj) == "object"
&& typeof(obj.length) == "number"
&& isFunction(obj.push);
}
等等。
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)
检查功能时,必须始终使用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
来检查功能的原因。
typeof
是错误的- f
以下是所有这些:(Object
对象)和Function
(函数)。除了我之外,使用它更有意义,instanceof
因为知道它是一个函数,我知道它也是一个对象,因为所有函数都是ECMAScript中的对象。反之则不正确-从中typeof
得知f
确实是一个object
我不知道它也是一个函数。
length
,name
并call
从功能,但所有的人都停止活动。更糟糕的是,它不能被调用并TypeError
说出:f is not a function
。
实际的重大差异:
var str = 'hello word';
str instanceof String // false
typeof str === 'string' // true
不要问我为什么。
str
是字符串基元,而不是字符串对象。数字基元和布尔基元也是如此,它们不是“构造的”对应物,字符串,数字和布尔对象的实例。JavaScript会在需要时自动将这三个原语转换为对象(例如,使用对象原型链上的方法)。在实际差异的另一面,instanceof更适合检查数组,因为typeof [] == "object" // true
。
性能
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
始终遵循对象的原型链,因此性能损失将取决于原型链中的类instanceof
是否受到测试。因此,对于较短的继承链,处罚将较低(例如[] instanceof Array
,{} instanceof Object
),而对于较长的处罚将更大。因此,如果同时obj instanceof SomeClass
和typeof obj !== 'string'
手段,从你的一些假设性的代码的角度相同(FE如果你只是做一个试验if
,而不是switch
通过多类等-ing),那么你最好挑第二个,性能,明智的,
这只是对这里所有其他解释的补充知识-我不建议在.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)
注意:列出功能的顺序在图像之间切换!
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"
尽管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
还有一种情况是,您只能进行排序instanceof
-返回true或false。随着typeof
你可以得到所提供的东西的类型
考虑到性能,您最好将typeof与典型的硬件配合使用,如果创建的脚本具有1000万次迭代循环,则指令:typeof str =='string'将花费9ms,而'string'instanceof String将花费19ms
当然很重要........!
让我们看一下示例,在我们的示例中,我们将以两种不同的方式声明函数。
我们将同时使用function declaration
和 Function Constructor。我们将如何SE typeof
和instanceof
的行为在这两个不同的方案。
使用函数声明创建函数:
function MyFunc(){ }
typeof Myfunc == 'function' // true
MyFunc instanceof Function // false
这种不同的结果可能的解释是,因为我们做了一个函数声明,typeof
可以理解,这是一个function.Because typeof
判断是否为上的typeof是操作上的表达,在我们的情况下实现的呼叫方法与否。如果实现了方法,则为函数,否则为非函数。为明确起见,检查ecmascript规范中的typeof。MyFunc
Call
使用函数构造函数创建函数:
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
无需过多考虑以上示例,只需记住以下两个观点:
typeof var;
是一元运算符,将返回var的原始类型或根类型。这样它会返回原始类型(string
,number
,bigint
,boolean
,undefined
,和symbol
)或object
类型。
对于更高级别的对象,例如内置对象(String,Number,Boolean,Array ..)或复杂或自定义对象,它们都是object
根类型,但是基于它们建立的实例类型是多种多样的(例如OOP类)继承概念),这里a instanceof A
-一个二进制运算符-将为您提供帮助,它将遍历原型链以检查是否出现了正确的操作数(A)的构造函数。
因此,每当您要检查“根类型”或使用原始变量时,请使用“ typeof”,否则请使用“ instanceof”。
null
这是一个特例,看似原始,但确实是对象的特例。使用a === null
检查null替代。
另一方面,function
也是一种特殊情况,它是内置对象但typeof
返回function
如您所见,instanceof
必须遍历原型链,而typeof
只需一次检查根类型,因此很容易理解为什么typeof
比instanceof
根据有关typeof的MDN文档,使用“ 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
。