在我的情况下:
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
instanceofJavascript中的代码可能会出现问题-我相信主要框架会尽量避免使用它。不同的窗口是打破窗口的方式之一-我相信类层次结构也可能使窗口混淆。
有更好的方法来测试对象是否为某种内置类型(通常是您想要的)。创建实用程序函数并使用它们:
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。