typeof 和 instanceof 之间有什么区别?何时应该使用其中之一?

发布于 2024-07-21 05:42:50 字数 427 浏览 13 评论 0原文

在我的特殊情况下:

callback instanceof Function

或者

typeof callback == "function"

甚至重要,有什么区别?

其他资源:

JavaScript-Garden typeof 与 < a href="http://bonsaiden.github.com/JavaScript-Garden/#types.instanceof" rel="noreferrer">instanceof

In my particular case:

callback instanceof Function

or

typeof callback == "function"

does it even matter, what's the difference?

Additional Resource:

JavaScript-Garden typeof vs instanceof

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(27

蓦然回首 2024-07-28 05:42:50

对自定义类型使用 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 custom types:

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 

Use typeof for simple built in types:

'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

Use instanceof for complex built in types:

/regularexpression/ instanceof RegExp; // true
typeof /regularexpression/; // object

[] instanceof Array; // true
typeof []; //object

{} instanceof Object; // true
typeof {}; // object

And the last one is a little bit tricky:

typeof null; // object
自由如风 2024-07-28 05:42:50

两者在功能上很相似,因为它们都返回类型信息,但我个人更喜欢 instanceof 因为它比较实际类型而不是字符串。 类型比较不太容易出现人为错误,而且在技术上速度更快,因为它是比较内存中的指针而不是进行整个字符串比较。

Both are similar in functionality because they both return type information, however I personally prefer instanceof because it's comparing actual types rather than strings. Type comparison is less prone to human error, and it's technically faster since it's comparing pointers in memory rather than doing whole string comparisons.

樱娆 2024-07-28 05:42:50

使用 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"

所以我认为这实际上取决于您正在检查的可能数据的类型。

A good reason to use typeof is if the variable may be undefined.

alert(typeof undefinedVariable); // alerts the string "undefined"
alert(undefinedVariable instanceof Object); // throws an exception

A good reason to use instanceof is if the variable may be null.

var myNullVar = null;
alert(typeof myNullVar ); // alerts the string "object"
alert(myNullVar  instanceof Object); // alerts "false"

So really in my opinion it would depend on what type of possible data you are checking.

无声静候 2024-07-28 05:42:50

为了清楚起见,您需要知道两个事实:

  1. instanceof 运算符测试 构造函数prototype 属性是否出现在 >对象的原型链。 在大多数情况下,这意味着该对象是通过使用此构造函数或其后代之一创建的。 但原型也可以通过 Object.setPrototypeOf() 方法 (ECMAScript 2015) 或通过 __proto__ 属性(旧浏览器,已弃用)显式设置。 但由于性能问题,不建议更改对象的原型。

因此instanceof仅适用于对象。 在大多数情况下,您不使用构造函数来创建字符串或数字。 你可以。 但你几乎从不这样做。

另外,instanceof 无法检查到底使用哪个构造函数来创建对象,但会返回 true,即使对象是从被检查的类派生的。 在大多数情况下,这是所需的行为,但有时并非如此。 所以你需要保持这个想法。

另一个问题是不同的作用域有不同的执行环境。 这意味着它们有不同的内置函数(不同的全局对象、不同的构造函数等)。 这可能会导致意想不到的结果。

例如,[] instanceof window.frames[0].Array 将返回 false,因为 Array.prototype !== window.frames[0].Array 和数组继承自前者。
此外,它不能用于未定义的值,因为它没有原型。

  1. typeof 运算符测试值是否属于六种基本类型之一:“数字”、“字符串”、 “布尔”、“对象”、“函数”或“未定义”。 其中字符串“object”属于所有对象(除了函数,它们是对象,但在 typeof 运算符中有自己的值),也属于“null”值和数组(对于“null”,这是一个错误,但这个错误太老了,因此它已成为标准)。 它不依赖于构造函数,即使值未定义也可以使用。 但它没有提供有关对象的任何详细信息。 因此,如果您需要它,请转到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);

upd:
自 ECMAScript 2015 以来,又多了一种称为 Symbol 的类型,它有自己的 typeof == "symbol"

console.log(typeof Symbol());
// expected output: "symbol"

您可以在 MDN 上阅读相关内容:(Symbol、typeof)。

To make things clear, you need to know two facts:

  1. The instanceof operator tests whether the prototype property of a constructor appears anywhere in the prototypes chain of an object. In most cases this mean that the object was created by using this constructor or one of its descendant. But also prototype may be set explicitly by Object.setPrototypeOf() method (ECMAScript 2015) or by the __proto__ property (old browsers, deprecated). Changing the prototype of an object is not recommended though, because of performance issues.

Thus instanceof is applicable only to objects. In most cases you aren't using constructors to create strings or numbers. You can. But you almost never do.

Also instanceof can't check, exactly which constructor was used to create the object, but will return true, even if object is derived from class which being checked. In most cases this is the desired behavior, but sometimes it's not. So you need to keep that mind.

Another problem is that different scopes have different execution environments. This means that they have different built-ins (different global object, different constructors, etc.). This may result in unexpected results.

For example, [] instanceof window.frames[0].Array will return false, because Array.prototype !== window.frames[0].Array and arrays inherit from the former.
Also, it cannot be used on undefined value, because it don't have a prototype.

  1. 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.

Now let's talk about one tricky thing. What if you use constructor to create a primitive type?

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

Seems like magic. But it is not. It's so-called boxing (wrapping primitive value by object) and unboxing (extracting wrapped primitive value from object). Such kind of code seems to be "a bit" fragile. Of course you can just avoid creating primitive type with constructors. But there is another possible situation, when boxing may hit you. When you use Function.call() or Function.apply() on a primitive type.

function test(){
  console.log(typeof this);
} 
test.apply(5);

To avoiding this you can use strict mode:

function test(){
  'use strict';
  console.log(typeof this);
} 
test.apply(5);

upd:
Since ECMAScript 2015, there is one more type called Symbol, which has its own typeof == "symbol".

console.log(typeof Symbol());
// expected output: "symbol"

You can read about it on MDN: (Symbol, typeof).

哥,最终变帅啦 2024-07-28 05:42:50

我在 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

所以从现在开始我将使用两者。

I've discovered some really interesting (read as "horrible") behavior in Safari 5 and Internet Explorer 9. I was using this with great success in Chrome and Firefox.

if (typeof this === 'string') {
    doStuffWith(this);
}

Then I test in IE9, and it doesn't work at all. Big surprise. But in Safari, it's intermittent! So I start debugging, and I find that Internet Explorer is always returning false. But the weirdest thing is that Safari seems to be doing some kind of optimization in its JavaScript VM where it is true the first time, but false every time you hit reload!

My brain almost exploded.

So now I've settled on this:

if (this instanceof String || typeof this === 'string')
    doStuffWith(this.toString());
}

And now everything works great. Note that you can call "a string".toString() and it just returns a copy of the string, i.e.

"a string".toString() === new String("a string").toString(); // true

So I'll be using both from now on.

黯淡〆 2024-07-28 05:42:50

我认为,当 callbackFunction 的子类型时,instanceof 也可以工作

instanceof also works when callback is a subtype of Function, I think

青丝拂面 2024-07-28 05:42:50

其他显着的实际差异:

// 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

Other Significant practical differences:

// 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
篱下浅笙歌 2024-07-28 05:42:50

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 进行比较,其行为如下:

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/

typeof: Per the MDN docmentation, typeof is a unary operator that returns a string indicating the type of the unevaluated operand.

In the case of string primitaves and string objects, typeof returns the following:

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: is a binary operator, accepting an object and a constructor. It returns a boolean indicating whether or not the object has the given constructor in its prototype chain.

When applied to the string instances above, and compared to String, it behaves as follows:

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

Reference: https://bambielli.com/til/2017-06-18-typeof-vs-instanceof/

旧话新听 2024-07-28 05:42:50

读完这篇文章后,我得出了一个自我结论,并创建了一个快速参考图表,并在 Chrome 中进行了测试。

可以选取首选单元格(粗体),涉及更简单的用例。

TYPESselftypeofinstanceofconstructor
nullnullobject
undefinedundefinedundefined
array [ ]Array.isArray([])objectArray
boolboolean布尔
数字数字
字符串字符串字符串
符号符号符号
函数函数Function函数
函数FunctionFunction
对象 {}object对象对象
正则表达式 /abc/objectRegExpRegExp
new Array()对象数组数组
new Boolean()objectBooleanBoolean
new Number()objectNumberNumber
new String()objectStringString
new myFunction()objectmyFunctionmyFunction
new myClass()objectmyClassmyClass

拇指规则:

  • 要检查基本类型,请使用 typeof
  • Null 可以检查为 myvar === null
  • 未定义可以通过myvar === undefined进行检查
  • Array可以使用Array.isArray([])进行检查
  • Object 可以使用 myvar instanceof Object 检查
  • Constructor 列可以以与 ({}).constructor 类似的方式使用代码>或<代码>([]).constructor

我承认,该指南并不完全正确,因为以不同的方式创建对象或类可能会导致意外的输出。 例如,使用 Object.create() 方法创建的对象或函数,大多数聪明人已经在线程中对此进行了解释

After reading this thread, I came out with a self conclusion and created a quick reference chart, tested in Chrome.

Preferred cells (in bold) can be picked up, involving a simpler usecase.

TYPESselftypeofinstanceofconstructor
nullnullobject
undefinedundefinedundefined
array []Array.isArray([])objectArray
boolbooleanBoolean
numbernumberNumber
stringstringString
symbolsymbolSymbol
functionfunctionFunctionFunction
classfunctionFunctionFunction
object {}objectObjectObject
RegExp /abc/objectRegExpRegExp
new Array()objectArrayArray
new Boolean()objectBooleanBoolean
new Number()objectNumberNumber
new String()objectStringString
new myFunction()objectmyFunctionmyFunction
new myClass()objectmyClassmyClass

Thumb Rule:

  • For checking primitive types use typeof
  • Null can be checked as myvar === null
  • Undefined can be checked as myvar === undefined
  • Array can be checked using Array.isArray([])
  • Object can be check using myvar instanceof Object
  • Constructor column can be utilized in a similar fashion as ({}).constructor or ([]).constructor

I admit, the guide is not fully correct, as Creating objects or classes in a different way can result in unexpected output. For example, objects or functions created using Object.create() method, which are already explained in the thread by most of the clever folks

凌乱心跳 2024-07-28 05:42:50

Javascript 中的 instanceof 可能很不稳定 - 我相信主要框架都试图避免使用它。 不同的窗口是它可能被破坏的方式之一 - 我相信类层次结构也会混淆它。

有更好的方法来测试对象是否是某种内置类型(这通常是您想要的)。 创建实用函数并使用它们:

function isFunction(obj) {
  return typeof(obj) == "function";
}
function isArray(obj) {
  return typeof(obj) == "object" 
      && typeof(obj.length) == "number" 
      && isFunction(obj.push);
}

等等。

instanceof in Javascript can be flaky - I believe major frameworks try to avoid its use. Different windows is one of the ways in which it can break - I believe class hierarchies can confuse it as well.

There are better ways for testing whether an object is a certain built-in type (which is usually what you want). Create utility functions and use them:

function isFunction(obj) {
  return typeof(obj) == "function";
}
function isArray(obj) {
  return typeof(obj) == "object" 
      && typeof(obj.length) == "number" 
      && isFunction(obj.push);
}

And so on.

吾性傲以野 2024-07-28 05:42:50

检查函数时,必须始终使用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 来检查函数的原因。

When checking for a function, one must always use typeof.

Here's the difference:

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

This is why one must never use instanceof to check for a function.

雨的味道风的声音 2024-07-28 05:42:50

这只是对这里所有其他解释的补充知识 - 我建议在任何地方使用.constructor

TL;DR:typeof 不可行的情况下,以及当您知道自己不关心原型链时 , 对象。 prototype.constructor 可以是比 instanceof 更可行甚至更好的替代方案:

x instanceof Y
x.constructor === Y

它自 1.1 起就已成为标准,因此无需担心向后兼容性。

穆罕默德·乌默 (Muhammad Umer) 也在此处的评论中简要提到了这一点。 它适用于具有原型的所有内容 - 因此所有内容都不是 nullundefined

// (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)

< a href="https://i.sstatic.net/RAsZd.png" rel="nofollow noreferrer">类型化数组实例与构造函数 - Chrome 64.0.3282.167(64 位,Windows)中速度提高 1.5 倍

Firefox 59.0b10(64 位,Windows)

类型化数组 instanceof 与构造函数 - 在 Firefox 59.0 中快 30 倍b10(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)

< img src="https://i.sstatic.net/gb4Si.png" alt="String/Number typeof 与构造函数 - Chrome 64.0.3282.167(64 位,Windows)中速度提高 1.26 倍">

< strong>Firefox 59.0b10(64位,Windows)

注意:功能列出的顺序在图像之间切换!

String/Number typeof 与构造函数 - 在 Firefox 59.0b10 中慢 0.78 倍 (64-位,Windows)

This is just complementary knowledge to all the other explanations here - I am not suggesting to use .constructor everywhere.

TL;DR: In situations where typeof is not an option, and when you know that you do not care about the prototype chain, Object.prototype.constructor can be a viable or even better alternative than instanceof:

x instanceof Y
x.constructor === Y

It's been in the standard since 1.1, so no worries about backwards compatibility.

Muhammad Umer briefly mentioned this in a comment somewhere here too. It works on everything with a prototype - so everything not null or 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

Furthermore, depending on your use case it can be a lot faster than instanceof (the reason likely being that it doesn't have to check the entire prototype chain). In my case I needed a fast way to check if a value is a typed array:

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

And the results:

Chrome 64.0.3282.167 (64-bit, Windows)

Typed Array instanceof vs constructor - 1.5x faster in Chrome 64.0.3282.167 (64-bit, Windows)

Firefox 59.0b10 (64-bit, Windows)

Typed Array instanceof vs constructor - 30x faster in Firefox 59.0b10 (64-bit, Windows)

Out of curiousity, I did a quick toy benchmark against typeof; surprisingly it doesn't perform much worse, and it seems even a bit faster in 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

NOTE: Order in which functions are listed switches between images!

Chrome 64.0.3282.167 (64-bit, Windows)

String/Number typeof vs constructor - 1.26x faster in Chrome 64.0.3282.167 (64-bit, Windows)

Firefox 59.0b10 (64-bit, Windows)

NOTE: Order in which functions are listed switches between images!

String/Number typeof vs constructor - 0.78x slower in Firefox 59.0b10 (64-bit, Windows)

━╋う一瞬間旳綻放 2024-07-28 05:42:50

instanceof 不适用于基元,例如 "foo" instanceof String 将返回 falsetypeof "foo" == "string"< /code> 将返回 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)

instanceof will not work for primitives eg "foo" instanceof String will return false whereas typeof "foo" == "string" will return true.

On the other hand typeof will probably not do what you want when it comes to custom objects (or classes, whatever you want to call them). For example:

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

It just so happens that functions are both 'function' primitives and instances of 'Function', which is a bit of an oddity given that it doesn't work like that for other primitive types eg.

(typeof function(){} == 'function') == (function(){} instanceof Function)

but

(typeof 'foo' == 'string') != ('foo' instanceof String)
萌能量女王 2024-07-28 05:42:50

我建议使用原型的callback.isFunction()

他们已经找出了差异,您可以信赖他们的理由。

我想其他 JS 框架也有这样的东西。

我相信 instanceOf 不适用于其他窗口中定义的函数。
它们的 Function 与您的 window.Function 不同。

I would recommend using prototype's callback.isFunction().

They've figured out the difference and you can count on their reason.

I guess other JS frameworks have such things, too.

instanceOf wouldn't work on functions defined in other windows, I believe.
Their Function is different than your window.Function.

你好,陌生人 2024-07-28 05:42:50

性能

在两者都适用的情况下,typeofinstanceof 更快。

根据您的引擎,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

Performance

typeof is faster than instanceof in situations where both are applicable.

Depending on your engine, the performance difference in favor of typeof could be around 20%. (Your mileage may vary)

Here is a benchmark testing for 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));

Result

instanceofTest took: 9.98 seconds.
typeofTest took: 8.33 seconds.
Performance ratio is: 1.198
谁的新欢旧爱 2024-07-28 05:42:50

无需被上面的大量示例淹没,只需记住两个观点:

  1. typeof var; 是一个一元运算符,将返回 var 的原始类型或根类型。 这样它将返回原始类型(string, number, bigint, boolean, undefined 和 symbol) 或 object 类型。

  2. 如果是更高级别的对象,例如内置对象(String、Number、Boolean、Array..)或复杂或自定义对象,它们都是 object 根类型,但实例基于它们构建的类型是不同的(就像OOP类继承概念),这里a instanceof A - 一个二元运算符 - 会帮助你,它会通过原型链来检查是否是正确操作数的构造函数(A) 是否出现。

因此,每当您想检查“根类型”或使用原始变量时,请使用“typeof”,否则使用“instanceof”。

null 是一种特殊情况,看似原始,但确实是对象的特殊情况。 使用 a === null 来检查 null。

另一方面,function也是一种特殊情况,它是内置对象,但typeof返回function

如您所见instanceof 必须遍历原型链,同时 typeof 只需检查一次根类型,因此很容易理解为什么 typeofinstanceof 更快代码>

no need to overwhelm with ton of above examples, just keep in mind two points of view:

  1. 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.

  2. 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.

so whenever you want to check "root type" or work with primitive variable - use "typeof", otherwise using "instanceof".

null is a special case,which is seemingly primitive, but indeed is a special case for object. Using a === null to check null instead.

on the other hand, function is also a special case, which is built-in object but typeof return function

as you can see instanceof must go through the prototype chain meanwhile typeof just check the root type one time so it's easy to understand why typeof is faster than instanceof

永言不败 2024-07-28 05:42:50

使用instanceof,因为如果更改类的名称,您将收到编译器错误。

Use instanceof because if you change the name of the class you will get a compiler error.

谁对谁错谁最难过 2024-07-28 05:42:50

显着的实际差异:

var str = 'hello word';

str instanceof String   // false

typeof str === 'string' // true

不要问我为什么。

Significant practical difference:

var str = 'hello word';

str instanceof String   // false

typeof str === 'string' // true

Don't ask me why.

一个人的旅程 2024-07-28 05:42:50
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"

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"

2024-07-28 05:42:50

根据关于 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

According to MDN documentation about typeof, objects instantiated with the "new" keyword are of type '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';

While documentation about instanceof points that:

const objectString = new String('String created with constructor');
objectString instanceOf String; // returns true
objectString instanceOf Object; // returns true

So if one wants to check e.g. that something is a string no matter how it was created, safest approach would be to use instanceof.

待"谢繁草 2024-07-28 05:42:50
/**
 * Did you ever heard of Anakandavada, the doctrine of manifoldness of reality?
 * 1) Check: typeof value === 'object'
 * 2) Check: value instanceof Object
 * 3) Check (1) *and* (2)
 * 4) neither
 * You may ponder to either use (1) or (2), but only (3) is right, because:
 * 1) Fails for functions, every function is also an object: Math.sqrt.test = "Hai"
 * 2) Fails for prototype-less objects: Object.create(null) instanceof Object === false.
 * @param {*} value - The actual value that we need to validate.
 * @returns {boolean} Boolean indicating if value is an object.
 */
function isObject(value) {
  return value instanceof Object || typeof value === 'object';
}
/**
 * Did you ever heard of Anakandavada, the doctrine of manifoldness of reality?
 * 1) Check: typeof value === 'object'
 * 2) Check: value instanceof Object
 * 3) Check (1) *and* (2)
 * 4) neither
 * You may ponder to either use (1) or (2), but only (3) is right, because:
 * 1) Fails for functions, every function is also an object: Math.sqrt.test = "Hai"
 * 2) Fails for prototype-less objects: Object.create(null) instanceof Object === false.
 * @param {*} value - The actual value that we need to validate.
 * @returns {boolean} Boolean indicating if value is an object.
 */
function isObject(value) {
  return value instanceof Object || typeof value === 'object';
}
梦中的蝴蝶 2024-07-28 05:42:50

非常准确地说
instanceof 应该用于通过构造函数(通常是自定义类型)创建值的地方,例如,

var d = new String("abc")

typeof 用于检查仅由赋值创建的值,例如

var d = "abc"

To be very precise
instanceof should be used where value is created via the constructor (generally custom types) for e.g.

var d = new String("abc")

whereas typeof to check values created just by assignments for e.g

var d = "abc"
三生一梦 2024-07-28 05:42:50

来自严格的面向对象的教育,我会选择

callback instanceof Function

字符串,因为它很容易出现我糟糕的拼写或其他拼写错误。 另外我觉得它读起来更好。

Coming from a strict OO upbringing I'd go for

callback instanceof Function

Strings are prone to either my awful spelling or other typos. Plus I feel it reads better.

短叹 2024-07-28 05:42:50

尽管 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

Despite instanceof may be a little bit faster then typeof, I prefer second one because of such a possible magic:

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
肥爪爪 2024-07-28 05:42:50

另一种情况是,您只能与 instanceof 进行比较 - 它返回 true 或 false。 使用 typeof 你可以获取所提供的something的类型

One more case is that You only can collate with instanceof - it returns true or false. With typeof you can get type of provided something

简美 2024-07-28 05:42:50

考虑到性能,你最好使用 typeof
使用典型的硬件,如果您创建一个循环 1000 万次迭代的脚本
指令: typeof str == 'string' 将花费 9ms
而 'string' instanceof String 将需要 19ms

with performance in mind, you'd better use typeof
with a typical hardware, if you create a script with a loop of 10 million iterations
the instruction: typeof str == 'string' will take 9ms
while 'string' instanceof String will take 19ms

分分钟 2024-07-28 05:42:50

当然重要......!

让我们通过示例来演示一下。在我们的示例中,我们将以两种不同的方式声明函数。

我们将同时使用函数声明函数构造函数。 我们将了解 typeofinstanceof 在这两种不同场景中的行为方式。

使用函数声明创建函数:

function MyFunc(){  }

typeof Myfunc == 'function' // true

MyFunc instanceof Function // false

对于这种不同结果的可能解释是,当我们进行函数声明时,typeof可以理解为它是一个函数。因为 typeof 检查 typeof 是否操作的表达式,在我们的例子中 MyFunc 已实现是否调用方法。 如果它实现 Call 方法,则它是一个函数。否则不是。为了澄清,请检查typeof 的 ecmascript 规范

使用函数构造函数创建函数:

var MyFunc2 = new Function('a','b','return a+b') // A function constructor is used 

typeof MyFunc2 == 'function' // true

MyFunc2 instanceof Function // true

这里typeof断言MyFunc2< /strong> 是一个函数以及 instanceof 运算符。我们已经知道 typeof 检查是否 MyFunc2 是否实现了 Call 方法。因为 MyFunc2 是一个函数并且它实现了 call 方法,这就是 typeof 知道它是一个函数的方式。另一方面,我们使用函数构造函数创建MyFunc2,它成为函数构造函数的实例code>。这就是为什么 instanceof 也解析为 true

使用什么更安全?

正如我们在这两种情况下看到的typeof运算符可以成功断言我们正在处理这里有一个函数,它比 instanceof 更安全。 如果函数声明instanceof将会失败,因为函数声明< /strong> 不是函数构造函数的实例。

最佳实践:

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

Of course it matters........ !

Let's walk this through with examples.In our example we will declare function in two different ways.

We will be using both function declaration and Function Constructor. We will se how typeof and instanceof behaves in those two different scenarios.

Create function using function declaration :

function MyFunc(){  }

typeof Myfunc == 'function' // true

MyFunc instanceof Function // false

Possible explanation for such different result is, as we made a function declaration , typeof can understand that it is a function.Because typeof checks whether or not the expression on which typeof is operation on, in our case MyFunc implemented Call Method or not. If it implements Call method it is a function.Otherwise not .For clarification check ecmascript specification for typeof.

Create function using function constructor :

var MyFunc2 = new Function('a','b','return a+b') // A function constructor is used 

typeof MyFunc2 == 'function' // true

MyFunc2 instanceof Function // true

Here typeof asserts that MyFunc2 is a function as well as the instanceof operator.We already know typeof check if MyFunc2 implemented Call method or not.As MyFunc2 is a function and it implements call method,that's how typeof knows that it's a function.On the other hand, we used function constructor to create MyFunc2, it becomes an instance of Function constructor.That's why instanceof also resolves to true.

What's safer to use ?

As we can see in both cases typeof operator can successfully asserted that we are dealing with a function here,it is safer than instanceof. instanceof will fail in case of function declaration because function declarations are not an instance of Function constructor.

Best practice :

As Gary Rafferty suggested, the best way should be using both typeof and instanceof together.

  function isFunction(functionItem) {

        return typeof(functionItem) == 'function' || functionItem instanceof Function;

  }

  isFunction(MyFunc) // invoke it by passing our test function as parameter
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文