typeof 和 instanceof 之间有什么区别,什么时候应该使用一个与另一个?

IT技术 javascript instanceof typeof
2021-01-28 16:32:10

在我的特殊情况下:

callback instanceof Function

或者

typeof callback == "function"

有什么区别吗?

额外资源:

JavaScript-Garden typeofinstanceof

6个回答

使用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
@Assimilater 你也可以将 instanceof 与函数一起使用,但是我认为这 3 条规则很容易记住,是的,函数是一个例外:)
2021-03-17 16:32:10
这个答案清楚为什么instaceof应该使用基本类型。很明显,在涉及自定义类型以及“对象”类型的好处时,您没有选择。但是是什么让函数与“简单的内置类型”混为一谈呢?我觉得一个函数的行为方式像一个对象很奇怪,但它的类型是 'function' 使得使用 'typeof' 变得可行。不过,你为什么要阻止 instanceof 呢?
2021-04-02 16:32:10
另一个棘手的部分 -> 'example string' instanceof String; // false 但 new String('example string') instanceof String; //真的
2021-04-10 16:32:10
Use instanceof for complex built in types- 这仍然容易出错。最好使用 ES5Array.isArray()等。或推荐的垫片。
2021-04-11 16:32:10
@Luke 像这样使用“新字符串”通常是个坏主意。创建一个“字符串对象”而不是字符串原语。请参阅此处的部分developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-04-12 16:32:10

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

这是错误的。它们并不相同。它们并不是在所有相同的情况下都能工作,尤其是在不同的 JavaScript 虚拟机和浏览器中。
2021-03-19 16:32:10
instanceof 处理同一窗口中的对象。如果您使用 iframe/frame 或 popup-windows,每个 (i)frame/window 都有自己的“function”对象,如果您尝试比较另一个 (i)frame/window 中的对象,instanceof 将失败。typeof 将适用于所有情况,因为它返回字符串“function”。
2021-03-24 16:32:10
您的回答是“两者在功能方面基本相同。” 恕我直言,这显然是错误的。正如我在回答中概述和解释的那样,这两个选项都不适用于所有情况——尤其是跨浏览器。更好的方法是将两者与 || 一起使用 操作员。
2021-03-24 16:32:10
在某些情况下,instanceof 无法按预期工作,而 typeof 工作正常... developer.mozilla.org/En/Core_JavaScript_1.5_Reference/ ...
2021-04-05 16:32:10
jsperf.com/typeof-function-vs-instanceof/3 我在 Chrome 和 FF3.X 上尝试过,“typeof”方法更快。
2021-04-07 16:32:10

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

所以在我看来,这取决于您正在检查的可能数据的类型。

在 Chrome 29.0.1541.0 中,devundefined instanceof Object返回 false,并且不会抛出异常。我不知道这种变化有多近,但它instanceof更有吸引力。
2021-03-14 16:32:10
+1 还请注意,instanceof不能与原始类型相比,typeof 可以。
2021-03-28 16:32:10
undefined instanceof Object不会抛出异常,因为,嗯,undefined已定义。该常量存在于命名空间中。当变量不存在时(例如由于拼写错误),instanceof 将抛出异常。另一方面,在不存在的变量上使用 typeof 会产生“未定义”。
2021-04-07 16:32:10

为了把事情说清楚,你需要知道两个事实:

  1. 的instanceof运算符测试是否原型属性一的构造函数中的任何地方出现的原型连锁的一个对象。在这意味着该对象在大多数情况下,创建通过使用此构造或者其后代的。但原型也可以通过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);

更新: 从 ECMAScript 2015 开始,还有一种类型叫做 Symbol,它有自己的 typeof == "symbol"

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

你可以在 MDN 上阅读它:(Symbol , typeof)。

不正确...从书中:“ github.com/getify/You-Dont-Know-JS ” Foo 的实例;// true instanceof 运算符将一个普通对象作为其左侧操作数,将一个函数作为其右侧操作数。问题instanceof的回答是:在a的整个[[Prototype]]链中,Foo.prototype任意指向的对象有没有出现过?
2021-03-21 16:32:10
此外,还添加了装箱/拆箱问题的说明。
2021-03-22 16:32:10
我已经编辑了答案,更正确。感谢您的评论。
2021-03-26 16:32:10
if an object is created by a given constructor 这是不正确的。 o instanceof C如果 o 继承自 C.prototype,则返回 true。您稍后在回答中提到了这方面的内容,但不是很清楚。
2021-03-28 16:32:10

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

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