Javascript:仍然对 instanceof 运算符感到困惑

     2023-02-22     12

关键词:

【中文标题】Javascript:仍然对 instanceof 运算符感到困惑【英文标题】:Javascript: Still confused by the instanceof operator 【发布时间】:2015-08-04 10:22:07 【问题描述】:

article 定义 instanceof 如下:

instanceof 操作符测试一个对象是否在其原型中 链接构造函数的原型属性。

这是一个公平的解释,生活很美好,直到我从 Eloquent Javascript 一书中看到这段代码:

function TextCell(text) 
  this.text = text.split("\n");


TextCell.prototype.minWidth = function() 
  return this.text.reduce(function(width, line) 
    return Math.max(width, line.length);
  , 0);


TextCell.prototype.minHeight = function() 
  return this.text.length;


TextCell.prototype.draw = function(width, height) 
  var result = [];
  for (var i = 0; i < height; i++) 
    var line = this.text[i] || "";
    result.push(line + repeat(" ", width - line.length));
  
  return result;


function RTextCell(text) 
  TextCell.call(this, text);


RTextCell.prototype = Object.create(TextCell.prototype);

RTextCell.prototype.draw = function(width, height) 
  var result = [];
  for (var i = 0; i < height; i++) 
    var line = this.text[i] || "";
    result.push(repeat(" ", width - line.length) + line);
  
  return result;
;

让我们创建一个 RTextCell 的实例并执行下面的 c

var rt = new RTextCell("ABC");
console.log(rt instanceof RTextCell); // true
console.log(rt instanceof TextCell); // true

我理解为什么第二个 console.log 的输出是“真”——因为构造函数 TextCell 是原型链的一部分。

但是第一个 console.log 让我感到困惑。

如果看代码(倒数第 10 行),RTextCell 的原型被更新为一个新的 Object,其原型设置为 TextCell.prototype。

RTextCell.prototype = Object.create(TextCell.prototype);.

看下面的快照,对象“rt”的原型链中没有提到构造函数“RTextCell”。那么,按照我在文章开头提到的定义,输出不应该是假的吗?为什么会返回真值?

我也阅读了this,但没有帮助我理解这个具体问题。

rt、RTextCell、TextCell 的快照按顺序见下文。

【问题讨论】:

这是一个结构很好的问题。您展示了您之前的所有调查,希望您得到很好的答案。 哦!我应该补充。我在 chrome 43.0.2357.65 和 firefox 33.1.1 上的上述快照中检查了这个原型链树。 【参考方案1】:
obj instanceof RTextCell

正在测试 RTextCell.prototype 是否存在于 obj 的原型链中。这是因为 obj 是使用新的 RTextCell 制作的。 RTextCell.prototype 的原型是 TextCell.prototype 的事实在这里是无关紧要的,似乎让你失望了。

RTextCell.prototype = Object.create(TextCell.prototype);

没有去掉RTextCell.prototype,它仍然是一个对象,但它的原型恰好是TextCell.prototype。

【讨论】:

【参考方案2】:

准确的措辞很重要。您说 构造函数 在原型链中,但原始引用没有:

instanceof 操作符测试一个对象是否在其原型中 链接构造函数的原型属性

所以表达式 rt instanceof RTextCell 实际上是在测试类似的东西(请记住 __proto__ 不是标准的):

var p = rt.__proto__;
while(p)

  if(p == RTextCell.prototype)
    return true;
  p = p.__proto__;

return false;

因此,即使函数 RTextCell 没有在上面的对象树中直接引用,RTextCell.prototype 对象也是。

【讨论】:

或在单个表达式中,RTextCell.prototype.isPrototypeOf(rt) :-) @Dark Falcon:之前我对 instanceof 运算符和 isPrototypeOf() 感到困惑,当我在 MDN 网站上查看定义中的“构造函数”一词时,我完全误解了。你的回答让我停顿了一下,意识到我错过了什么。 “措辞”。现在它是有道理的。我也刚刚阅读了 [this].(***.com/questions/18343545/…) 以了解 instanceof 和 isPrototypeOf() 之间的区别。谢谢老兄。【参考方案3】:

您确实更改了RTextCell.prototype,但您在构造任何RTextCell 实例之前更改了它。考虑这个完全不同的示例,其中 RTextCell.prototype 在使用原始原型创建实例后被修改:

var rt = new RTextCell();
RTextCell.prototype = somethingTotallyDifferent;
rt instanceof RTextCell; // false!

rt 创建时,rt.__proto__ === RTextCell.prototype 是真的。一旦RTextCell.prototype 发生变化,这就不再是真的了。

您不是在测试 rt 在其原型链中是否具有来自RTextCell原始 prototype 属性。相反,您正在测试 RTextCell.prototype right now 的值是否存在于对象的原型链中。对于RTextCell 实例,这始终是正确的,因为RTextCell 构造函数创建的实例总是在其原型链中获得RTextCell.prototype 的当前值,并且在开始构造实例后您永远不会更改RTextCell.prototype

【讨论】:

除了@Dark Falcon 的回答之外,您将原型设置为“somethingTotallyDifferent”的示例对我有所帮助。这是有道理的。谢谢。

理解javascript_07_理解instanceof实现原理

在《Javascript类型检测》一文中讲到了用instanceof来用做检测类型,让我们来回顾一下: 那么instanceof的这种行为到底是如何实现的呢,现在让我们揭开instanceof背后的迷雾。 instanceof原理照惯例,我们先来看一段代码:12345678910... 查看详情

javascript中的typeof和instanceof

typeof是一元操作符,而instanceof是二元操作符;typeof操作的是一个变量,而instanceof前面是一个变量,后面是一个类型;typeof返回的是一个字符串,而instanceof返回的是一个布尔值。1、typeof()http://www.cnblogs.com/jikey/archive/2010/05/05/172833... 查看详情

JavaScript - instanceof 没有按照我的预期做

】JavaScript-instanceof没有按照我的预期做【英文标题】:JavaScript-instanceofnotdoingwhatIexpect【发布时间】:2016-07-0614:32:14【问题描述】:如果我错了,请原谅我,但我认为这样做:functionMyObject()returnkey:\'value\',hello:function()console.log(\'wor... 查看详情

javascript使用instanceof验证object的构造函数(代码片段)

查看详情

在 JavaScript 中使用 instanceof 运算符是性能问题吗? [关闭]

】在JavaScript中使用instanceof运算符是性能问题吗?[关闭]【英文标题】:Isusinginstanceofoperatorinjavascriptaperformanceissue?[closed]【发布时间】:2010-12-3100:33:09【问题描述】:听说java中的instanceof操作符是个性能问题,Javascript也是这样吗... 查看详情

前端面试javascript—instanceof能否判断基本数据类型?(代码片段)

能。比如下面这种方式:classCheckNumberTypestatic[Symbol.hasInstance](x)returntypeofx==='number';console.log(100instanceofCheckNumberType);//true其实就是自定义instanceof行为的一种方式,这里将原有的instanceof方法重定义,换成了... 查看详情

对javascript的深入理解

1.一切(引用类型)都是对象,对象是属性的集合。2.判断一个变量是否是对象。值类型(undefined,number,string,boolean)的类型判断用typeof,引用类型(函数,数组,对象,null,newNumber)的类型判断用instanceof。其中typeof判断引用类型... 查看详情

javascript中typeof,instanceof,hasownproperty,in的用法和区别

一.typeof操作符typeof操作符用于返回正在使用值的类型。//使用原始值letmNull=null;letmUndefined=undefined;letmString=‘mazey‘;letmNumber=123;letmBoolean=true;letmFunction=function(){returntrue;};//用构造函数的方式new一个实例letoString=newStr 查看详情

在 Java 中使用 instanceof 对性能的影响

】在Java中使用instanceof对性能的影响【英文标题】:TheperformanceimpactofusinginstanceofinJava【发布时间】:2010-09-1108:09:44【问题描述】:我正在开发一个应用程序,其中一种设计方法涉及大量使用instanceof运算符。虽然我知道OO设计通常... 查看详情

javascript23_instanceof和hasown

13、instanceof和hasOwninstanceof用来检查一个对象是否是一个类的实例instanceof检查的是对象的原型链上是否有该类实例只要原型链上有该类实例,就会返回truedog->Animal的实例->Object实例->Object原型Object是所有对象的原型,所以任... 查看详情

如何对泛型类型列表进行 instanceof 检查?

】如何对泛型类型列表进行instanceof检查?【英文标题】:Howcanidoaninstanceofcheckonagenericstypelist?【发布时间】:2017-11-2906:33:30【问题描述】:我正在编写一个方法,它可以采用3个不同对象的不同列表,每个对象都扩展同一个超类。... 查看详情

typeof和instanceof的认识

前言在javascript中,存在着六种基础数据类型,分为值类型(“undefined”,”boolean”,“Null”,“Number ”,“String”)和引用类型(“object ”,“Function”)instanceof在JavaScript中,判断一个变量的类型尝尝会用typeof运算... 查看详情

instanceof

instanceof运算符简介在JavaScript中,判断一个变量的类型尝尝会用typeof运算符,在使用typeof运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回"object"。ECMAScript引入了另一个Java运算符instanceof来... 查看详情

typeof&instanceof原理

...这一类型,如果用typeof判断,会得到object的结果。因为在Javascript底层存储变量的时候,会在变量的机器码低位1-3位表示类型信息。而null的低位1-3解析到的为000,而000表示的是obecjt类型。答案依然是NO,因为null根本没有__proto__属... 查看详情

“instanceof”怎么读

JavaScript中的二元操作符参考技术A音四疼恩斯饿肤本回答被提问者采纳 参考技术Bdict.baidu.com中搜索instance和of有音标 查看详情

无法对参数化类型 ArrayList<Foo> 执行 instanceof 检查

】无法对参数化类型ArrayList<Foo>执行instanceof检查【英文标题】:CannotperforminstanceofcheckagainstparameterizedtypeArrayList<Foo>【发布时间】:2011-09-0713:51:39【问题描述】:以下代码:((tempVarinstanceofArrayList<Foo>)?tempVar:null);原因... 查看详情

javascript探索--3

typeof与instanceof判断字符串类型可用typeOf,但判断数组,对象,正则,null时,返回的都是Object,所以可用instanceof来判断类型<script>varstr=‘Lee‘;alert(typeofstr);//stringvararr=[1,2,3];alert(typeofarr);//objectalert(arrinstanceofArray); 查看详情

需要了解 Javascript 对象引用 [重复]

】需要了解Javascript对象引用[重复]【英文标题】:NeedtounderstandJavascriptobjectreferences[duplicate]【发布时间】:2015-01-1211:52:34【问题描述】:我正在查看JohnResig网站上的这段代码。我不明白的是,当ninja对象设置为空对象时,yell方法... 查看详情