- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
在此代码段中,语句 f instanceof PipeWritable
返回 true(Node v8.4.0):
const stream = require('stream');
const fs = require('fs');
class PipeWritable extends stream.Writable {
constructor () {
super();
}
}
const s = new PipeWritable();
const f = fs.createWriteStream('/tmp/test');
console.log(f instanceof PipeWritable); // true ... ???
对象s
:
Object.getPrototypeOf(s)
是 PipeWritable {}
s.constructor
是 [Function: PipeWritable]
PipeWritable.prototype
是 PipeWritable {}
对象 f
:
Object.getPrototypeOf(f)
是 WriteStream { ... }
f.constructor
是 [Function: WriteStream] ...
stream.WriteStream.prototype
是 Writable { ... }
原型(prototype)链:
Object f Object s
--------------------- --------------------
Writable PipeWritable
Stream Writable
EventEmitter Stream
Object EventEmitter
Object
The instanceof operator tests whether an object in its prototype chain has the prototype property of a constructor.
我希望 (f instanceof PipeWritable) === false
,因为 PipeWritable
不在 f
的原型(prototype)链中(上面的链通过调用 Object.getPrototypeOf(...)
) 进行验证。
但它返回 true
,因此我的分析有问题。
正确答案是什么?
最佳答案
这是由于 Node.js 源代码中的某个部分代码,在 _stream_writable.js
中:
var realHasInstance;
if (typeof Symbol === 'function' && Symbol.hasInstance) {
realHasInstance = Function.prototype[Symbol.hasInstance];
Object.defineProperty(Writable, Symbol.hasInstance, {
value: function(object) {
if (realHasInstance.call(this, object))
return true;
return object && object._writableState instanceof WritableState;
}
});
} else {
realHasInstance = function(object) {
return object instanceof this;
};
}
作者 language specification , instanceof
运算符使用众所周知的符号 @@hasInstance
检查对象 O 是否是构造函数 C 的实例:
12.9.4 Runtime Semantics: InstanceofOperator(O, C)
The abstract operation InstanceofOperator(O, C) implements the generic algorithm for determining if an object O inherits from the inheritance path defined by constructor C. This abstract operation performs the following steps:
- If Type(C) is not Object, throw a TypeError exception.
- Let instOfHandler be GetMethod(C,@@hasInstance).
- ReturnIfAbrupt(instOfHandler).
- If instOfHandler is not undefined, then
a. Return ToBoolean(Call(instOfHandler, C, «O»)).- If IsCallable(C) is false, throw a TypeError exception.
- Return OrdinaryHasInstance(C, O).
现在让我为你逐段分解上面的代码:
var realHasInstance;
if (typeof Symbol === 'function' && Symbol.hasInstance) {
…
} else {
…
}
上面的代码片段定义了 realHasInstance
, 检查是否 Symbol
已定义,如果众所周知的符号 hasInstance
存在。在您的情况下,确实如此,因此我们将忽略 else
分支。下一个:
realHasInstance = Function.prototype[Symbol.hasInstance];
这里,realHasInstance
分配给 Function.prototype[@@hasInstance]
:
19.2.3.6 Function.prototype[@@hasInstance] ( V )
When the @@hasInstance method of an object F is called with value V, the following steps are taken:
- Let F be the this value.
- Return OrdinaryHasInstance(F, V).
@@hasInstance
Function
的方法|只需调用 OrdinaryHasInstance。下一个:
Object.defineProperty(Writable, Symbol.hasInstance, {
value: function(object) {
if (realHasInstance.call(this, object))
return true;
return object && object._writableState instanceof WritableState;
}
});
这在 Writable
上定义了一个新属性构造函数,著名符号hasInstance
-- 基本上实现了它自己的自定义版本 hasInstance
. hasInstance
的值是一个接受一个参数的函数,即 instanceof
正在测试的对象, 在这种情况下 f
.
下一行 if 语句检查是否 realHasInstance.call(this, object)
是真实的。前面提到过,realHasInstance
分配给 Function.prototype[@@hasInstance]
这实际上是调用内部操作OrdinaryHasInstance(C, O) . OrdinaryHasInstance 操作只是通过在原型(prototype)链中查找构造函数来检查 O 是否是您和 MDN 描述的 C 的实例。
在这种情况下,可写 f
不是 Writable ( PipeWritable
) 子类的实例,因此 realHasInstance.call(this, object)
是假的。既然是假的,就转到下一行:
return object && object._writableState instanceof WritableState;
自从 object
, 或 f
在这种情况下,是真实的,并且因为 f
是一个可写的 _writableState
作为 WritableState
实例的属性, f instanceof PipeWritable
是真实。
这个实现的原因是在 comments :
// Test _writableState for inheritance to account for Duplex streams,
// whose prototype chain only points to Readable.
因为双工流在技术上是可写的,但它们的原型(prototype)链只指向可读,额外检查是否 _writableState
是 WritableState
的一个实例允许 duplexInstance instanceof Writable
是真实的。这有一个您发现的副作用 - Writable 是“子类的实例”。这是一个错误,应该报告。
这实际上甚至在 documentation 中都有报道。 :
Note: The
stream.Duplex
class prototypically inherits fromstream.Readable
and parasitically fromstream.Writable
, butinstanceof
will work properly for both base classes due to overridingSymbol.hasInstance
onstream.Writable
.
从 Writable 寄生继承会有一些后果,如下所示。
我提交了 issue on GitHub看起来它会被修复。如Bergi mentioned ,添加检查以查看 this === Writable
,确保在使用 instanceof
时只有双工流是 Writable 的实例.有一个pull request .
关于javascript - 为什么 instanceof 在这里评估为真?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45772705/
这个问题在这里已经有了答案: 关闭 12 年前。 Possible Duplicate: Why can't Python handle true/false values as I expect?
我是不是遗漏了什么或者这是 ruby 中的错误? a = %w(foo bar baz) a.include? "foo" # => true a.size == 3
从 Modelica 文档来看,注释 Evaluate 似乎只对参数有影响: https://build.openmodelica.org/Documentation/ModelicaReferenc
为了避免嵌套的 if 语句并提高可读性,我想创建一个switch(true){ ... } Coldfusion 中的声明。我在 php 中经常使用这个,但是当我在 Coldfusion 中尝试这个时
嗨,我正在尝试处理 ajax json 响应 这是我的代码 success: function (j) { switch(true) { case (j.cho
我之前在我的 TF 代码中使用过这个: count = "${var.whatever == "true" ? 1 : 0}" 这非常适合我想要使用的东西。但是,我正在考虑如何最好地使用类似于说的
我之前在我的 TF 代码中使用过这个: count = "${var.whatever == "true" ? 1 : 0}" 这非常适合我想要使用的东西。但是,我正在考虑如何最好地使用类似于说的
这个问题在这里已经有了答案: How can I return pivot table output in MySQL? (10 个答案) 关闭 5 年前。 我正在尝试构建一个以唯一列值作为列名的表
我制作了一个简单的 JDialog,其中包含一个标签和一个按钮,它基本上相当于信息对话框。所以在对话框中,有一个方法 display() 我在其中调用了 setVisible(true) 五次。 据我
在 bash 4.2.8(1)-release (x86_64-pc-linux-gnu) 在 Ubuntu 11.04 上这个命令 [ $(wc -l /var/www/some.log|cut -
我正在使用 c 语言进行并发处理,我有一个进程池。为此,我让每个 child 都在一个 While (True) 循环中。为了杀死 child ,我正在使用一个全局变量和一个信号处理程序来修改它来打破
我正在尝试选择填写了字段的数据库条目。数据库有两种插入数据的方式,一种输入评论,一种不输入,我希望只选择填写了评论的行。 $requete = "SELECT * FROM daysoff WHER
如何在 JavaMail session 中setDebug(true) 捕获流并在我的日志记录框架中使用它? (缺少下载源代码,更改接受流作为参数的方法,重新编译它,...) 更一般地说,Java
我是 JavaScript 的新手,我刚刚发现了我无法理解的奇怪行为: var magicVar = Math.sin; magicVar == true; // it returns false m
对此感到困惑。 在两台服务器上运行相同版本的 MySQL。 (从完全相同的 rpm 构建)- 沿线的某个地方,一些开发人员改变了一些东西...... 服务器 1: mysql> select ( no
我在查看 OpenSSL 中使用的一些预处理器宏时,从 crypto/stack/safestack.h 中发现了以下内容: #define CHECKED_STACK_OF(type, p) \
所以我遇到了一个问题,我的正则表达式看起来像这样:/true|false/。 当我检查单词 falsee 时,我从这个正则表达式中得到一个 true,有没有办法将它限制为确切的 true 或 fals
我正在对这个恶意 JavaScript 行进行一些试验:var undefined = true; JavaScript 中每个未初始化的变量都有 undefined 的值,这只是一个保存特殊值 'u
我想将 PHP 的微时间存储为我在 MySQL 中的时间戳。 我去过told最好用 DECIMAL 存储它,但我找不到理想的大小。 有谁知道 microtime(true) 返回的最大大小是多少,所以
在 PHP 中,当您在 URL 中包含诸如“var=true”之类的内容时,URL 中的“true”和“false”是否被转换为 boolean 变量,或者它们是否等于文本“true”还是“假”?例如
我是一名优秀的程序员,十分优秀!