JavaScript 中的 instanceof 运算符是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2449254/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 00:24:43  来源:igfitidea点击:

What is the instanceof operator in JavaScript?

javascriptoperatorsinstanceof

提问by Alon Gubkin

The instanceofkeyword in JavaScript can be quite confusing when it is first encountered, as people tend to think that JavaScript is not an object-oriented programming language.

instanceofJavaScript 中的关键字在第一次遇到时可能会非常令人困惑,因为人们往往认为 JavaScript 不是面向对象的编程语言。

  • What is it?
  • What problems does it solve?
  • When is it appropriate and when not?
  • 它是什么?
  • 它解决了哪些问题?
  • 什么时候合适,什么时候不合适?

采纳答案by JonH

instanceof

实例

The Left Hand Side (LHS) operand is the actual object being tested to the Right Hand Side (RHS) operand which is the actual constructor of a class. The basic definition is:

左侧 (LHS) 操作数是被测试到右侧 (RHS) 操作数的实际对象,右侧 (RHS) 操作数是类的实际构造函数。基本定义是:

Checks the current object and returns true if the object
is of the specified object type.

Here are some good examplesand here is an example taken directly from Mozilla's developer site:

这里有一些很好的例子,这里有一个直接取自Mozilla 开发者网站的例子:

var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral"; //no type specified
color2 instanceof String; // returns false (color2 is not a String object)

One thing worth mentioning is instanceofevaluates to true if the object inherits from the classe's prototype:

值得一提的是instanceof,如果对象继承自类的原型,则评估为 true:

var p = new Person("Jon");
p instanceof Person

That is p instanceof Personis true since pinherits from Person.prototype.

这是p instanceof Person真的,因为p继承自Person.prototype.

Per the OP's request

根据 OP 的要求

I've added a small example with some sample code and an explanation.

我添加了一个带有一些示例代码和解释的小示例。

When you declare a variable you give it a specific type.

当你声明一个变量时,你给它一个特定的类型。

For instance:

例如:

int i;
float f;
Customer c;

The above show you some variables, namely i, f, and c. The types are integer, floatand a user defined Customerdata type. Types such as the above could be for any language, not just JavaScript. However, with JavaScript when you declare a variable you don't explicitly define a type, var x, x could be a number / string / a user defined data type. So what instanceofdoes is it checks the object to see if it is of the type specified so from above taking the Customerobject we could do:

上面显示一些变量,即ifc。类型是integer,float和用户定义的Customer数据类型。上面的类型可以用于任何语言,而不仅仅是 JavaScript。但是,对于 JavaScript,当您声明一个变量时,您没有明确定义类型,var x, x 可以是数字/字符串/用户定义的数据类型。那么instanceof它的作用是检查对象以查看它是否属于指定的类型,因此从上面获取Customer我们可以做的对象:

var c = new Customer();
c instanceof Customer; //Returns true as c is just a customer
c instanceof String; //Returns false as c is not a string, it's a customer silly!

Above we've seen that cwas declared with the type Customer. We've new'd it and checked whether it is of type Customeror not. Sure is, it returns true. Then still using the Customerobject we check if it is a String. Nope, definitely not a Stringwe newed a Customerobject not a Stringobject. In this case, it returns false.

上面我们已经看到,它c是用类型声明的Customer。我们已经对它进行了新的检查并检查了它是否属于类型Customer。当然,它返回真。然后仍然使用该Customer对象,我们检查它是否是String. 不,绝对不是String我们更新了一个Customer对象而不是一个String对象。在这种情况下,它返回 false。

It really is that simple!

真的就是这么简单!

回答by webnesto

There's an important facet to instanceof that does not seem to be covered in any of the comments thus far: inheritance. A variable being evaluated by use of instanceof could return true for multiple "types" due to prototypal inheritance.

到目前为止,任何评论中似乎都没有涵盖 instanceof 的一个重要方面:继承。由于原型继承,使用 instanceof 评估的变量可能为多个“类型”返回 true。

For example, let's define a type and a subtype:

例如,让我们定义一个类型和一个子类型:

function Foo(){ //a Foo constructor
    //assign some props
    return this;
}

function SubFoo(){ //a SubFoo constructor
    Foo.call( this ); //inherit static props
    //assign some new props
    return this;
}

SubFoo.prototype = Object.create(Foo.prototype); // Inherit prototype
SubFoo.prototype.constructor = SubFoo;

Now that we have a couple of "classes" lets make some instances, and find out what they're instances of:

现在我们有几个“类”,让我们创建一些实例,并找出它们的实例:

var 
    foo = new Foo()
,   subfoo = new SubFoo()
;

alert( 
    "Q: Is foo an instance of Foo? "
+   "A: " + ( foo instanceof Foo ) 
); // -> true

alert( 
    "Q: Is foo an instance of SubFoo? " 
+   "A: " + ( foo instanceof SubFoo ) 
); // -> false

alert( 
    "Q: Is subfoo an instance of Foo? "
+   "A: " + ( subfoo instanceof Foo ) 
); // -> true

alert( 
    "Q: Is subfoo an instance of SubFoo? "
+   "A: " + ( subfoo instanceof SubFoo ) 
); // -> true

alert( 
    "Q: Is subfoo an instance of Object? "
+   "A: " + ( subfoo instanceof Object ) 
); // -> true

See that last line? All "new" calls to a function return an object that inherits from Object. This holds true even when using object creation shorthand:

看到最后一行了吗?对函数的所有“新”调用都返回一个从 Object 继承的对象。即使在使用对象创建速记时也是如此:

alert( 
    "Q: Is {} an instance of Object? "
+   "A: " + ( {} instanceof Object ) 
); // -> true

And what about the "class" definitions themselves? What are they instances of?

那么“类”定义本身呢?它们是什么实例?

alert( 
    "Q: Is Foo an instance of Object? "
+   "A:" + ( Foo instanceof Object) 
); // -> true

alert( 
    "Q: Is Foo an instance of Function? "
+   "A:" + ( Foo instanceof Function) 
); // -> true

I feel that understanding that any object can be an instance of MULTIPLE types is important, since you my (incorrectly) assume that you could differentiate between, say and object and a function by use of instanceof. As this last example clearly shows a function isan object.

我觉得理解任何对象都可以是 MULTIPLE 类型的实例很重要,因为您(错误地)假设您可以通过使用instanceof. 正如最后一个例子清楚地表明一个函数一个对象。

This is also important if you are using any inheritance patterns and want to confirm the progeny of an object by methods other than duck-typing.

如果您正在使用任何继承模式并希望通过鸭子类型以外的方法确认对象的后代,这也很重要。

Hope that helps anyone exploring instanceof.

希望可以帮助任何人探索instanceof

回答by Jay Conrod

The other answers here are correct, but they don't get into how instanceofactually works, which may be of interest to some language lawyers out there.

这里的其他答案是正确的,但它们没有instanceof涉及实际工作方式,这可能是一些语言律师感兴趣的。

Every object in JavaScript has a prototype, accessible through the __proto__property. Functions also have a prototypeproperty, which is the initial __proto__for any objects created by them. When a function is created, it is given a unique object for prototype. The instanceofoperator uses this uniqueness to give you an answer. Here's what instanceofmight look like if you wrote it as a function.

JavaScript 中的每个对象都有一个原型,可以通过__proto__属性访问。函数也有一个prototype属性,它是__proto__由它们创建的任何对象的初始值。当一个函数被创建时,它被赋予一个唯一的对象prototype。该instanceof操作员使用这种独特性给你一个答案。以下是instanceof可能的样子,如果你写一个函数。

function instance_of(V, F) {
  var O = F.prototype;
  V = V.__proto__;
  while (true) {
    if (V === null)
      return false;
    if (O === V)
      return true;
    V = V.__proto__;
  }
}

This is basically paraphrasing ECMA-262 edition 5.1 (also known as ES5), section 15.3.5.3.

这基本上是对 ECMA-262 5.1 版(也称为 ES5)第 15.3.5.3 节的解释。

Note that you can reassign any object to a function's prototypeproperty, and you can reassign an object's __proto__property after it is constructed. This will give you some interesting results:

请注意,您可以将任何对象重新分配给函数的prototype属性,并且可以__proto__在构造后重新分配对象的属性。这会给你一些有趣的结果:

function F() { }
function G() { }
var p = {};
F.prototype = p;
G.prototype = p;
var f = new F();
var g = new G();

f instanceof F;   // returns true
f instanceof G;   // returns true
g instanceof F;   // returns true
g instanceof G;   // returns true

F.prototype = {};
f instanceof F;   // returns false
g.__proto__ = {};
g instanceof G;   // returns false

回答by Stephen Belanger

I think it's worth noting that instanceof is defined by the use of the "new" keyword when declaring the object. In the example from JonH;

我认为值得注意的是,instanceof 是通过在声明对象时使用“new”关键字来定义的。在 JonH 的例子中;

var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral";
color2 instanceof String; // returns false (color2 is not a String object)

What he didn't mention is this;

他没有提到的是这个;

var color1 = String("green");
color1 instanceof String; // returns false

Specifying "new" actually copied the end state of the String constructor function into the color1 var, rather than just setting it to the return value. I think this better shows what the new keyword does;

指定“new”实际上是将 String 构造函数的结束状态复制到 color1 变量中,而不仅仅是将其设置为返回值。我认为这更好地说明了 new 关键字的作用;

function Test(name){
    this.test = function(){
        return 'This will only work through the "new" keyword.';
    }
    return name;
}

var test = new Test('test');
test.test(); // returns 'This will only work through the "new" keyword.'
test // returns the instance object of the Test() function.

var test = Test('test');
test.test(); // throws TypeError: Object #<Test> has no method 'test'
test // returns 'test'

Using "new" assigns the value of "this" inside the function to the declared var, while not using it assigns the return value instead.

使用“new”将函数内“this”的值分配给声明的var,而不使用它分配返回值。

回答by Tarek Saied

And you can use it for error handling and debugging, like this:

您可以将其用于错误处理和调试,如下所示:

try{
    somefunction();
} 
catch(error){
    if (error instanceof TypeError) {
        // Handle type Error
    } else if (error instanceof ReferenceError) {
        // Handle ReferenceError
    } else {
        // Handle all other error types
    }
}

回答by yfeldblum

//Vehicle is a function. But by naming conventions
//(first letter is uppercase), it is also an object
//constructor function ("class").
function Vehicle(numWheels) {
    this.numWheels = numWheels;
}

//We can create new instances and check their types.
myRoadster = new Vehicle(4);
alert(myRoadster instanceof Vehicle);

回答by Willem van der Veen

What is it?

它是什么?

Javascript is a prototypal language which means it uses prototypes for 'inheritance'. the instanceofoperator tests if a constructor function's prototypepropertype is present in the __proto__chain of an object. This means that it will do the following (assuming that testObj is a function object):

Javascript 是一种原型语言,这意味着它使用原型进行“继承”。所述instanceof,如果一个构造函数的操作者测试prototypepropertype存在于__proto__一个对象的链。这意味着它将执行以下操作(假设 testObj 是一个函数对象):

obj instanceof testObj;
  1. Check if prototype of the object is equal to the prototype of the constructor: obj.__proto__ === testObj.prototype>> if this is trueinstanceofwill return true.
  2. Will climb up the prototype chain. For example: obj.__proto__.__proto__ === testObj.prototype>> if this is trueinstanceofwill return true.
  3. Will repeat step 2 until the full prototype of object is inspected. If nowhere on the prototype chain of the object is matched with testObj.prototypethen instanceofoperator will return false.
  1. 检查对象的原型是否等于构造函数的原型:obj.__proto__ === testObj.prototype>> 如果是,trueinstanceof则返回true
  2. 将爬上原型链。例如:obj.__proto__.__proto__ === testObj.prototype>> 如果这是trueinstanceof将返回true
  3. 将重复步骤 2,直到检查对象的完整原型。如果对象的原型链上没有任何地方与之匹配,testObj.prototypeinstanceof运算符将返回false

Example:

例子:

function Person(name) {
  this.name = name;
}
var me = new Person('Willem');

console.log(me instanceof Person); // true
// because:  me.__proto__ === Person.prototype  // evaluates true

console.log(me instanceof Object); // true
// because:  me.__proto__.__proto__ === Object.prototype  // evaluates true

console.log(me instanceof Array);  // false
// because: Array is nowhere on the prototype chain

What problems does it solve?

它解决了哪些问题?

It solved the problem of conveniently checking if an object derives from a certain prototype. For example, when a function recieves an object which can have various prototypes. Then, before using methods from the prototype chain, we can use the instanceofoperator to check whether the these methods are on the object.

它解决了方便检查对象是否来自某个原型的问题。例如,当一个函数收到一个可以有各种原型的对象时。然后,在使用原型链中的方法之前,我们可以使用instanceof操作符来检查这些方法是否在对象上。

Example:

例子:

function Person1 (name) {
  this.name = name;
}

function Person2 (name) {
  this.name = name;
}

Person1.prototype.talkP1 = function () {
  console.log('Person 1 talking');
}

Person2.prototype.talkP2 = function () {
  console.log('Person 2 talking');
}


function talk (person) {
  if (person instanceof Person1) {
    person.talkP1();
  }
  
  if (person instanceof Person2) {
    person.talkP2();
  }
  
  
}

const pers1 = new Person1 ('p1');
const pers2 = new Person2 ('p2');

talk(pers1);
talk(pers2);

Here in the talk()function first is checked if the prototype is located on the object. After this the appropriate method is picked to execute. Not doing this check could result in executing a method which doesn't exist and thus a reference error.

talk()函数中,首先检查原型是否位于对象上。在此之后,选择适当的方法来执行。不执行此检查可能会导致执行不存在的方法,从而导致引用错误。

When is it appropriate and when not?

什么时候合适,什么时候不合适?

We kind of already went over this. Use it when you are in need of checking the prototype of an object before doing something with it.

我们已经有点过了。当您需要在使用对象之前检查对象的原型时使用它。

回答by Willem van der Veen

instanceofis just syntactic sugar for isPrototypeOf:

instanceof只是语法糖isPrototypeOf

function Ctor() {}
var o = new Ctor();

o instanceof Ctor; // true
Ctor.prototype.isPrototypeOf(o); // true

o instanceof Ctor === Ctor.prototype.isPrototypeOf(o); // equivalent

instanceofjust depends on the prototype of a constructor of an object.

instanceof只取决于对象构造函数的原型。

A constructor is just a normal function. Strictly speaking it is a function object, since everything is an object in Javascript. And this function object has a prototype, because every function has a prototype.

构造函数只是一个普通的函数。严格来说它是一个函数对象,因为在 Javascript 中一切都是对象。而这个函数对象有一个原型,因为每个函数都有一个原型。

A prototype is just a normal object, which is located within the prototype chain of another object. That means being in the prototype chain of another object makes an object to a prototype:

原型只是一个普通对象,它位于另一个对象的原型链中。这意味着在另一个对象的原型链中使对象成为原型:

function f() {} //  ordinary function
var o = {}, // ordinary object
 p;

f.prototype = o; // oops, o is a prototype now
p = new f(); // oops, f is a constructor now

o.isPrototypeOf(p); // true
p instanceof f; // true

The instanceofoperator should be avoided because it fakes classes, which do not exist in Javascript. Despite the classkeyword not in ES2015 either, since classis again just syntactic sugar for...but that's another story.

instanceof应该避免使用运算符,因为它伪造了 Javascript 中不存在的类。尽管class关键字不在 ES2015 中,因为class它再次只是语法糖...但那是另一回事了。

回答by Andrew Magee

On the question "When is it appropriate and when not?", my 2 cents:

关于“什么时候合适,什么时候不合适?”的问题,我的 2 美分:

instanceofis rarely useful in production code, but useful in tests where you want to assert that your code returns / creates objects of the correct types. By being explicit about the kinds of objects your code is returning / creating, your tests become more powerful as a tool for understanding and documenting your code.

instanceof在生产代码中很少有用,但在您想要断言代码返回/创建正确类型的对象的测试中很有用。通过明确您的代码返回/创建的对象类型,您的测试作为理解和记录代码的工具变得更加强大。

回答by jussty

I just found a real-world application and will use it more often now, I think.

我刚刚找到了一个真实世界的应用程序,我想现在会更频繁地使用它。

If you use jQuery events, sometimes you want to write a more generic function which may also be called directly (without event). You can use instanceofto check if the first parameter of your function is an instance of jQuery.Eventand react appropriately.

如果您使用 jQuery 事件,有时您想编写一个更通用的函数,它也可以直接调用(没有事件)。您可以使用instanceof来检查函数的第一个参数是否是 的实例jQuery.Event并做出适当的反应。

var myFunction = function (el) {                
    if (el instanceof $.Event) 
        // event specific code
    else
        // generic code
};

$('button').click(recalc);    // Will execute event specific code
recalc('myParameter');  // Will execute generic code

In my case, the function needed to calculate something either for all (via click event on a button) or only one specific element. The code I used:

就我而言,该函数需要为所有人(通过按钮上的单击事件)或仅一个特定元素计算某些内容。我使用的代码:

var recalc = function (el) { 
    el = (el == undefined || el instanceof $.Event) ? $('span.allItems') : $(el);
    // calculate...
};