typeof和instanceof有什么区别,何时应该使用另一个?

far*_*ace 368 javascript typeof instanceof

在我的特殊情况下:

callback instanceof Function
Run Code Online (Sandbox Code Playgroud)

要么

typeof callback == "function"
Run Code Online (Sandbox Code Playgroud)

甚至重要,有什么区别?

额外资源:

JavaScript-Garden typeof vs instanceof

Szy*_*ski 504

使用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 
Run Code Online (Sandbox Code Playgroud)

使用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
Run Code Online (Sandbox Code Playgroud)

使用instanceof了内建类型复杂:

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

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

{} instanceof Object; // true
typeof {}; // object
Run Code Online (Sandbox Code Playgroud)

而最后一个有点棘手:

typeof null; // object
Run Code Online (Sandbox Code Playgroud)

  • 这个答案清楚地表明为什么instaceof应该**不能用于原始类型.很明显,当涉及到自定义类型时,你没有选项,以及"对象"类型的好处.但是什么使得函数与"简单的内置类型"混为一谈?我发现一个函数如何像一个对象一样奇怪,但它的类型是'function',使得'typeof'可行.你为什么不劝阻它呢? (8认同)
  • `对于复杂的内置类型使用instanceof` - 这仍然容易出错.最好使用ES5`Array.isArray()`等.或推荐的垫片. (4认同)
  • @Assimilater你可以将instanceof与函数一起使用,但我认为这3条规则很容易记住,是的,函数是一个例外:) (3认同)
  • 另一个棘手的部分 - >'example string'instanceof String; // false但是新的String('example string')instanceof String; //真正 (2认同)
  • @Luke一般不会像这样使用"new String".这会创建一个"字符串对象"而不是字符串基元.请参阅此处的部分https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String (2认同)

Sov*_*iut 121

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

  • instanceof使用同一窗口中的对象.如果您使用iframe/frame或popup-windows每个(i)帧/窗口都有自己的"函数"对象,如果您尝试比较另一个(i)帧/窗口中的对象,则instanceof将失败.typeof将在所有情况下都有效,因为它返回字符串"function". (54认同)
  • http://jsperf.com/typeof-function-vs-instanceof/3我试过Chrome和FF3.X,"typeof"方法更快. (13认同)
  • 这只是假的.它们不完全相同.它们不会在所有相同的情况下工作,尤其是在不同的JavaScript VM和浏览器中. (8认同)
  • 在某些情况下,instanceof将无法按预期工作,并且typeof运行良好... https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Operators/Special_Operators/Instanceof_Operator#Description (7认同)
  • 你的回答是"两者在功能上基本相同." 恭敬地,这显然是错误的.正如在我的回答中所概述和解释的那样,这两种选择都不适用于所有情况 - 尤其是跨浏 更好的方法是同时使用|| 运营商. (7认同)
  • JS 的许多实现(我知道 V8 有,不确定其他实现)都有 `typeof something === "type"` 特殊情况,所以没有真正的字符串比较。 (2认同)

Ken*_*h J 96

使用typeof的一个很好的理由是变量可能未定义.

alert(typeof undefinedVariable); // alerts the string "undefined"
alert(undefinedVariable instanceof Object); // throws an exception
Run Code Online (Sandbox Code Playgroud)

使用instanceof的一个很好的理由是变量可能为null.

var myNullVar = null;
alert(typeof myNullVar ); // alerts the string "object"
alert(myNullVar  instanceof Object); // alerts "false"
Run Code Online (Sandbox Code Playgroud)

所以我认为这取决于您检查的数据类型.

  • +1还注意到`instanceof`无法与原始类型比较,typeof可以. (11认同)
  • `undefined instanceof Object`不会抛出异常,因为,呃,'undefined`被定义了.常量存在于命名空间中.当变量不存在时(例如由于拼写错误),instanceof将抛出异常.另一方面,在不存在的变量上使用typeof会产生'undefined'. (6认同)
  • 在Chrome 29.0.1541.0中,dev`undefined instanceof Object`返回false,并且不会抛出异常.我不知道最近的改变是什么,但它使`instanceof`更具吸引力. (3认同)

Vla*_*mov 27

为了弄清楚,你需要知道两个事实:

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

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

instanceof也无法检查,确切地使用了哪个构造函数来创建对象,但是返回true,即使object是从被检查的类派生的.在大多数情况下,这是期望的行为,但有时并非如此.所以你需要保持这种想法.

另一个问题是不同的范围具有不同的执行环境.这意味着它们具有不同的内置函数(不同的全局对象,不同的构造函数等).这可能会导致意外结果.

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

  1. typeof运算操作测试值是否属于六种基本类型之一:" 号码 "," "," 布尔 "," 对象 "," 函数 "或" 不确定 ".字符串"object"属于所有对象(函数除外,它们是对象,但在typeof运算符中有自己的值),还有"null"值和数组(对于"null",它是一个bug,但是这个bug太旧了,所以它成为一个标准).它不依赖于构造函数,即使值未定义也可以使用.但它没有提供有关对象的任何细节.因此,如果您需要它,请转到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
Run Code Online (Sandbox Code Playgroud)

看起来像魔术.但事实并非如此.它就是所谓的装箱(按对象包装原始值)和拆箱(从对象中提取包装的原始值).这种代码似乎"有点"脆弱.当然,您可以避免使用构造函数创建基本类型.但还有另一种可能的情况,拳击可能会打你.在基本类型上使用Function.call()或Function.apply()时.

function test(){
  console.log(typeof this);
} 
test.apply(5);
Run Code Online (Sandbox Code Playgroud)

要避免这种情况,您可以使用严格模式:

function test(){
  'use strict';
  console.log(typeof this);
} 
test.apply(5);
Run Code Online (Sandbox Code Playgroud)

upd: 自ECMAScript 2015以来,还有一个名为Symbol的类型,它有自己的typeof == "symbol".

console.log(typeof Symbol());
// expected output: "symbol"
Run Code Online (Sandbox Code Playgroud)

您可以在MDN上阅读它:( 符号,typeof).

  • `如果对象是由给定的构造函数创建的`这是不正确的.如果o继承自C.prototype,则`o instanceof C`将返回true.您在答案中稍后提到了一些相关内容,但目前尚不清楚. (2认同)

Jus*_*rce 14

我在Safari 5和Internet Explorer 9中发现了一些非常有趣(读作"可怕")的行为.我在Chrome和Firefox中使用它非常成功.

if (typeof this === 'string') {
    doStuffWith(this);
}
Run Code Online (Sandbox Code Playgroud)

然后我在IE9中测试,它根本不起作用.大惊喜.但在Safari中,它是断断续续的!所以我开始调试,我发现Internet Explorer 总是返回false.但最奇怪的是,Safari浏览器似乎是在做某种在它的JavaScript虚拟机优化的地方是true第一时间,但false 每次你打一次重装!

我的大脑几乎爆炸了.

所以现在我已经解决了这个问题:

if (this instanceof String || typeof this === 'string')
    doStuffWith(this.toString());
}
Run Code Online (Sandbox Code Playgroud)

现在一切都很好.请注意,您可以调用"a string".toString()它只返回字符串的副本,即

"a string".toString() === new String("a string").toString(); // true
Run Code Online (Sandbox Code Playgroud)

所以我从现在开始都会使用它们.


San*_*ath 8

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'
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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


new*_*cct 7

instanceof我认为,当它callback是一个子类型时也有用Function


小智 7

其他重大的实际差异:

// 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
Run Code Online (Sandbox Code Playgroud)


lev*_*vik 5

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

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

function isFunction(obj) {
  return typeof(obj) == "function";
}
function isArray(obj) {
  return typeof(obj) == "object" 
      && typeof(obj.length) == "number" 
      && isFunction(obj.push);
}
Run Code Online (Sandbox Code Playgroud)

等等。

  • @some 你对 typeof 是对的,但在这种情况下不需要 ===,只有当被比较的值可能相等而不具有相同类型时才需要它。在这里,不能。 (6认同)
  • 如果您不知道: typeof 不需要括号,因为它是关键字而不是函数。恕我直言,您应该使用 === 而不是 ==。 (3认同)

小智 5

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

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

类型 自己 类型 实例化 构造函数
无效的 无效的 目的
不明确的 不明确的 不明确的
大批 [] Array.isArray([]) 目的 大批
布尔值 布尔值 布尔值
数字 数字 数字
细绳 细绳 细绳
象征 象征 象征
功能 功能 功能 功能
班级 功能 功能 功能
目的 {} 目的 目的 目的
正则表达式 /abc/ 目的 正则表达式 正则表达式
新数组() 目的 大批 大批
新布尔值() 目的 布尔值 布尔值
新号码() 目的 数字 数字
新字符串() 目的 细绳 细绳
新的 myFunction() 目的 我的函数 我的函数
新的我的类() 目的 我的课 我的课

拇指规则:

  • 为了检查原始类型使用typeof
  • Null可以检查为myvar === null
  • 未定义可以检查为myvar === undefined
  • 可以使用检查数组Array.isArray([])
  • 可以使用检查对象myvar instanceof Object
  • 构造函数列可以以类似的方式使用({}).constructor([]).constructor

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