instanceof如何在JavaScript中运行? [英] How does instanceof work in JavaScript?

查看:76
本文介绍了instanceof如何在JavaScript中运行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码示例中,最后使用 instanceof 检查obj2和obj3,即使构造的方式不同,返回 name 的结果也会返回true属性不同。

  var Obj1 = function(){
this.name =foo1;
};
Obj1.prototype.name =foo1onProt;
var obj1 = new Obj1();

var Obj2 = function(){};
Obj2.prototype = new Obj1();
Obj2.prototype.constructor = Obj2;
var obj2 = new Obj2();

var Obj3 = function(){};
Obj3.prototype = Object.create(Obj1.prototype);
Obj3.prototype.constructor = Obj3;
var obj3 = new Obj3();

console.dir(obj1);
console.log(obj1.name:+ obj1.name);

console.dir(obj2);
console.log(obj2.name:+ obj2.name);

console.dir(obj3);
console.log(obj3.name:+ obj3.name);

console.log(obj2 instanceof Obj1:+(obj2 instanceof Obj1));
console.log(obj3 instanceof Obj1:+(obj3 instanceof Obj1));

在Chrome中运行的结果:

  Obj1 
名称:foo1
__proto__:对象
构造函数:function(){
name:foo1onProt
__proto__:Object
obj1.name:foo1
Obj2
__proto__:Obj1
构造函数:function(){}
名称:foo1
__proto__: Object
构造函数:function(){
name:foo1onProt
__proto__:Object
obj2.name:foo1
Obj3
__proto__:Object
构造函数:function(){}
__proto__:Object
构造函数:function(){
name:foo1onProt
__proto__:Object
obj3.name: foo1onProt

obj2 instanceof Obj1:true
obj3 instanceof Obj1:true

识别 obj2 obj3 的最佳方法是什么?
实际上 instanceof 是如何工作的?

解决方案


什么是识别obj2和obj3不同的最好方法吗?


这将取决于你在做什么。一种方法是使用 instanceof Obj2 instanceof Obj3 。由于两个对象都是在原型链中使用 Obj1.prototype 创建的,因此它们确定为我们在基于类的OOP中称为超类型的实例。


实际上如何工作?




短版



obj instanceof F 查看 F引用的对象.prototype 位于 obj 的原型链中。它根本不使用构造函数



更多细节



§11.8.5 - 在规范中对此进行了介绍 - 运营商 的实例,(间接通过§8.6.2)它调用函数对象的 [[HasInstance]] 内部方法,传入对象我们'重新测试。 功能 [[HasInstance]] (在§15.3.5.3)说它从函数的原型获取对象引用 property然后返回 true 如果该对象在目标对象的原型链中的任何位置, false 如果它没有't。



它不使用构造函数(事实上,JavaScript本身没有任何内容) &mdash ;如果你考虑它,它不能,因为一个对象的构造函数属性只能指向一个函数,但一个对象可以是 instanceof 多个功能 —例如,在伪经典继承的情况下:



  function F1(){} function F2(){F1.call(this) ;} F2.prototype = Object.create(F1.prototype); F2.prototype.constructor = F2; var obj = new F2(); snippet.log(obj instanceof F1); // truesnippet.log(obj instanceof F2); // true  

 <! - 脚本提供` snippet`对象,请参阅http://meta.stackexchange.com/a/242144/134069  - >< script src =http://tjcrowder.github.io/simple-snippets-console/snippet.js >< / script>  



两者都是真的因为两个 F1.prototype F2.prototype 引用的对象都在 obj 的原型链。



instanceof 为真并不一定意味着 obj 是通过直接或间接调用 F 创建的;它只是表明它们之间存在模糊的联系( F.prototype 指的是同样位于 obj 的原型中的对象链)。 通常意味着 F 参与创建对象,但无法保证。



例如:



  function F(){} var obj = Object.create(F.prototype); snippet.log(obj instanceof F ); // true  

 < script src =http:/ /tjcrowder.github.io/simple-snippets-console/snippet.js\"></script>  



注意,根本没有调用 F 来创建对象。






或者可能更清楚和/或更显着:



  function F(){ } var p = {}; var obj = Object.create(p); snippet.log(obj instanceof F); // falseF.prototype = p; snippet.log(obj instanceof F); // true  

 < script src =http:/ /tjcrowder.github.io/simple-snippets-console/snippet.js\"></script>  






还有这个不寻常但完全可能的版本:



  function F1(){} function F2(){} F1.prototype = F2.prototype = {}; var obj = new F1(); snippet.log(obj instanceof F2); // true  

 < script src =http:/ /tjcrowder.github.io/simple-snippets-console/snippet.js\"></script>  






或者这一个:



  function F1( ){}函数F2(){} var obj = new F2(); snippet.log(obj instanceof F1); // falseF1.prototype = F2.prototype; snippet.log(obj instanceof F1); // true  

 < script src =http:/ /tjcrowder.github.io/simple-snippets-console/snippet.js\"></script>  


In the following code sample both checks of obj2 and obj3 at the end with instanceof return true even if the ways there were constructed are different and the results of returning name property are different.

var Obj1 = function() {
    this.name = "foo1";
};
Obj1.prototype.name = "foo1onProt";
var obj1 = new Obj1();

var Obj2 = function() {};
Obj2.prototype = new Obj1();
Obj2.prototype.constructor = Obj2;
var obj2 = new Obj2();

var Obj3 = function() {};
Obj3.prototype = Object.create(Obj1.prototype);
Obj3.prototype.constructor = Obj3;
var obj3 = new Obj3();

console.dir(obj1);
console.log("obj1.name: " + obj1.name);

console.dir(obj2);
console.log("obj2.name: " + obj2.name);

console.dir(obj3);
console.log("obj3.name: " + obj3.name);

console.log("obj2 instanceof Obj1: " + (obj2 instanceof Obj1));
console.log("obj3 instanceof Obj1: " + (obj3 instanceof Obj1));

Result of the run in Chrome:

Obj1
  name: "foo1"
  __proto__: Object
    constructor: function () {
    name: "foo1onProt"
    __proto__: Object
obj1.name: foo1
Obj2
  __proto__: Obj1
    constructor: function () {}
    name: "foo1"
    __proto__: Object
      constructor: function () {
      name: "foo1onProt"
      __proto__: Object
obj2.name: foo1
Obj3
   __proto__: Object
   constructor: function () {}
   __proto__: Object
     constructor: function () {
     name: "foo1onProt"
     __proto__: Object
obj3.name: foo1onProt

obj2 instanceof Obj1: true
obj3 instanceof Obj1: true

What is the best way to recognize that obj2 and obj3 are different? How does actually instanceof work?

解决方案

What is the best way to recognize that obj2 and obj3 are different?

That will depend a great deal on what you're doing with them. One way would be to use instanceof Obj2 and instanceof Obj3. Since both objects were created with Obj1.prototype in their prototype chain, it makes sense that they identify as being an instance of what we would call the supertype in class-based OOP.

How does actually instanceof work?

The short version

obj instanceof F looks to see if the object referenced by F.prototype is anywhere in obj's prototype chain. It doesn't use constructor at all.

More details

This is covered in the spec by §11.8.5 - The instanceof Operator, which says (indirectly, via §8.6.2) that it calls the [[HasInstance]] internal method of the function object, passing in the object we're testing. Function's [[HasInstance]] (in §15.3.5.3) says that it gets the object reference from the function's prototype property and then returns true if that object is anywhere in the target object's prototype chain, false if it doesn't.

It doesn't use constructor (nothing in JavaScript itself does, in fact) — and if you think about it, it can't, because an object's constructor property can only point at one function, but an object can be instanceof multiple functions — for instance, in the case of pseudo-classical inheritance:

function F1() {}

function F2() {
  F1.call(this);
}
F2.prototype = Object.create(F1.prototype);
F2.prototype.constructor = F2;

var obj = new F2();
snippet.log(obj instanceof F1); // true
snippet.log(obj instanceof F2); // true

<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Both are true because the two objects referenced by F1.prototype and F2.prototype are both in obj's prototype chain.

instanceof being true doesn't necessarily mean that obj was created by a call to F, either directly or indirectly; it just indicates there's a vague link between them (F.prototype refers to an object that's also in obj's prototype chain). It usually means F was involved in creating the object, but there's no guarantee.

For instance:

function F() {}
var obj = Object.create(F.prototype);
snippet.log(obj instanceof F); // true

<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Note that F wasn't called to create the object, at all.


Or perhaps more clearly and/or dramatically:

function F() {}
var p = {};
var obj = Object.create(p);
snippet.log(obj instanceof F); // false
F.prototype = p;
snippet.log(obj instanceof F); // true

<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>


There's also this unusual, but entirely possible, version:

function F1() {}
function F2() {}
F1.prototype = F2.prototype = {};
var obj = new F1();
snippet.log(obj instanceof F2); // true

<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>


Or this one:

function F1() {}
function F2() {}
var obj = new F2();
snippet.log(obj instanceof F1); // false
F1.prototype = F2.prototype;
snippet.log(obj instanceof F1); // true

<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

这篇关于instanceof如何在JavaScript中运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆