typeof和instanceof之间的区别是什么?何时应该使用另一个?

本文翻译自:What is the difference between typeof and instanceof and when should one be used vs. the other?

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 JavaScript-Garden typeof vs instanceof


#1楼

参考:https://stackoom.com/question/3m1G/typeof和instanceof之间的区别是什么-何时应该使用另一个


#2楼

A good reason to use typeof is if the variable may be undefined. 使用typeof的一个很好的理由是变量可能未定义。

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. 使用instanceof的一个很好的理由是变量可能为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. 所以我认为这取决于您检查的数据类型。


#3楼

Performance 性能

typeof is faster than instanceof in situations where both are applicable. 在两者都适用的情况下, typeofinstanceof更快。

Depending on your engine, the performance difference in favor of typeof could be around 20% . 根据您的引擎,有利于typeof的性能差异可能在20%左右 ( Your mileage may vary ) 你的里程可能有所不同

Here is a benchmark testing for Array : 这是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

#4楼

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. instanceof运算符测试构造函数prototype属性是否出现在对象的原型链中的任何位置。 In most cases this mean that the object was created by using this constructor or on of its descendant. 在大多数情况下,这意味着该目标是通过使用此构造或者其后代的创建 But also prototype may be set explicitly by Object.setPrototypeOf() method (ECMAScript 2015) or by the __proto__ property (old browsers, deprecated). 但也可以通过Object.setPrototypeOf()方法(ECMAScript 2015)或__proto__属性(旧浏览器,不推荐使用)显式设置原型。 Changing the prototype of an object is not recommended though, because of performance issues. 但是,由于性能问题,不建议更改对象的原型。

Thus instanceof is applicable only to objects. 因此,instanceof仅适用于对象。 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. instanceof也无法检查,确切地使用了哪个构造函数来创建对象,但是返回true,即使object是从被检查的类派生的。 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. 例如, [] instanceof window.frames[0].Array将返回false ,因为Array.prototype !== window.frames[0].Array和数组继承自前者。
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 ". typeof运算符测试值是否属于六种基本类型之一 :“ number ”,“ string ”,“ boolean ”,“ object ”,“ function ”或“ 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). 字符串“object”属于所有对象(函数除外,它们是对象,但在typeof运算符中有自己的值),还有“null”值和数组(对于“null”,它是一个bug,但是这个bug太旧了,所以它成为一个标准)。 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. 因此,如果您需要它,请转到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.call()或Function.apply()时。

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" . upd:自ECMAScript 2015以来,还有一个名为Symbol的类型,它有自己的typeof == “symbol”

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

You can read about it on MDN: ( Symbol , typeof ). 您可以在MDN上阅读它:( 符号typeof )。


#5楼

Significant practical difference: 显着的实际差异:

var str = 'hello word';

str instanceof String   // false

typeof str === 'string' // true

Don't ask me why. 不要问我为什么。


#6楼

Despite instanceof may be a little bit faster then typeof , I prefer second one because of such a possible magic: 虽然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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值