Javascript 为什么可以';我是否初始化导入的属性而不首先将其分配给变量?
以下代码可以正常工作:Javascript 为什么可以';我是否初始化导入的属性而不首先将其分配给变量?,javascript,new-operator,Javascript,New Operator,以下代码可以正常工作: const Readable=require('stream')。可读; const readStream=新的可读数据流; 使用此代码,readStream是一个Readable实例。但是,当我尝试使用以下代码消除多余的行时,它不再起作用: const readStream=new require('stream')。可读; 使用此代码,readStream不是可读的实例,而是可读的函数本身。令人惊讶的是,以下代码运行良好: const readStream=new
const Readable=require('stream')。可读;
const readStream=新的可读数据流;
使用此代码,readStream
是一个Readable
实例。但是,当我尝试使用以下代码消除多余的行时,它不再起作用:
const readStream=new require('stream')。可读;
使用此代码,readStream
不是可读的
实例,而是可读的
函数本身。令人惊讶的是,以下代码运行良好:
const readStream=new require('stream').Readable();
使用此代码,readStream
是一个Readable
实例,而不是Readable
函数。这是我想要的行为
这是怎么回事?为什么不先将函数赋给变量就不能初始化函数?如果必须为变量赋值,那么为什么最后一个代码可以正常工作?原因在于新的
运算符的工作方式。JavaScript的一个特性是new
操作符可以使用括号,也可以不使用括号:
//这两种方法都有效,因为“new”运算符可以在没有括号的情况下使用
const request_和_括号=new XMLHttpRequest();
不带括号的常量请求=新的XMLHttpRequest;
它的工作方式是,直到第一对括号结束的所有内容都成为new
表达式的一部分。如果没有一对括号,则整个表达式将成为new
表达式的一部分。示例:
newdate().getMonth())
//相当于:
(新日期()).getMonth()
新日期().getMonth
//相当于:
(新日期()).getMonth
新日期。getMonth()
//相当于:
(新日期。getMonth())
新的Date.getMonth
//相当于:
(新日期。getMonth)
//这相当于:
(新日期。getMonth())
顺便说一下,需要注意的是,所谓“括号”,我指的是函数调用括号。我不是指把括号分组
所以,回到可读的示例:
const readStream=new require('stream')。可读;
//相当于:
const readStream=(new require('stream'))。可读;
因此,我们实际上是用new
操作符调用“require”函数。关于如何工作的快速提醒:
创建一个空白的普通JavaScript对象李>
通过将另一个对象设置为其父原型,将新创建的对象链接(设置其构造函数)到另一个对象李>
将步骤1中新创建的对象作为此上下文传递李>
如果函数不返回对象,则返回此值
因此,如果new
操作符操作的函数没有返回对象,则new
操作符具有一个功能。另一方面,如果new
操作符操作的函数已经返回了一个对象,那么new
操作符没有任何效果。因为“require”函数已经返回了一个对象,所以用new
操作符调用它没有效果。它本质上相当于在不使用new
操作符的情况下调用它。这使我们想到:
const readStream=new require('stream')。可读;
//等效于(由于'new'运算符的解析规则):
const readStream=(new require('stream'))。可读;
//等价于(因为'new'运算符对已返回内容的函数没有影响)
const readStream=(require('stream'))。可读;
因此,该代码的基本功能是:
导入流模块
获取对可读函数的引用,而不创建其实例
但是下面的代码呢
const readStream=new require('stream').Readable();
这段代码确实返回了一个可读的实例。由于其按预期工作,因此代码必须等效于:
const Readable=require('stream')。可读;
const readStream=new Readable();
而不是:
const readStream=(新的require('stream')).Readable();
换句话说,由于此代码按预期工作,新的
运算符必须与第二对括号(可读的
之后的括号)相关联,而不是与第一对括号(需要的之后的括号)相关联,对吗?这意味着new
运算符并不总是与第一对括号关联。有时,它也可以与第二对括号关联。当new
操作符与第二对括号关联而不是与第一对括号关联时,我们应该如何判断
否。新的
操作符总是与第一对括号关联。它与第二对或更高的括号相关联。如果是这样的话,上面的代码是如何工作的?这是因为可读函数是如何实现的。上述代码之所以有效,是因为Readable
函数返回一个新的可读实例,即使在没有新运算符的情况下调用它也是如此。换句话说,无论您如何调用Readable
函数(使用或不使用new
操作符),它总是返回Readable的新实例。因此,守则:
const readStream=new require('stream').Readable();
实际上相当于:
const readStream=(新的require('stream')).Readable();
这并不等同于:
const Readable=require('stream')。可读;
const readStream=new Readable();
它工作的原因很简单,因为Readable
函数是如何实现的。换句话说,一直以来,使用new
操作符都是不必要的!最初的代码可能是:
const readStream=require('