ChatGPT解决这个技术问题 Extra ChatGPT

“require(x)”和“import x”的区别

我刚刚开始研究一个将与 MongoDB 交互的小型节点项目。但是,我似乎无法正确导入相关节点模块,即使我已通过 npm 正确安装它们。

例如,下面的代码会抛出一个错误,告诉我“express 没有默认导出”:

import express from "express";

但是,此代码有效:

const express = require("express");

所以我的问题是,import 和 variable/require 方法的功能有什么区别?我想解决困扰我在项目中的导入的任何问题,因为它似乎可能会在未来引起其他问题。

除非包含 express 的类型定义,否则第一种形式没有意义 - 在这种情况下,您可以使用第二种形式,但变量 express 的类型将是 any。您可以在此处包含定义 npmjs.com/package/@types/express
@Ryall 这是不同的问题。注意 import x = require('x')var x = require('x') 不同。

A
AndrewGentry

这个简单的图表将帮助您了解 requireimport 之间的区别。

https://i.stack.imgur.com/5WgFJ.png

除此之外,

不能使用 require 选择性地仅加载您需要的片段,但使用 import,您可以选择性地仅加载您需要的片段,这可以节省内存。

require 的加载是同步的(逐步),而 import 可以是异步的(无需等待之前的导入),因此它的性能比 require


影响代码的最大区别是 CommonJS 模块中的导出是“计算的”,而 ESM 模块中的导出是静态的(预定义的)。 JS 仅在解析代码(尚未运行它)后就可以确定 ESM 模块中的导出。在 commonJS 模块中,导出仅在模块实际运行时才知道,并且您会在模块初始化代码完成运行时看到分配给 module.exports 的内容。在尝试使单个模块同时适用于 ESM 和 CommonJS 时,仅此差异就会造成兼容性问题。
ESM 模块对打包程序更友好,但对编码员的限制更大,因为您不能在 ESM 模块中进行计算导出。
u
user1063287

requireimport 的主要区别在于 require 会自动扫描 node_modules 以查找模块,而来自 ES6 的 import 不会。

大多数人使用 babel 来编译 importexport,这使得 import 的行为与 require 相同。

Node.js 的未来版本可能会支持 import 本身(实际上是 the experimental version already does),从 Node.js 的注释来看,import 不会支持 node_modules,它基于 ES6,并且必须指定模块的路径。

所以我建议你不要在 babel 中使用 import,但是这个功能还没有确认,将来可能会支持 node_modules,谁知道呢?

作为参考,下面是 babel 如何将 ES6 的 import 语法转换为 CommonJS 的 require 语法的示例。

假设文件app_es6.js包含此导入:

import format from 'date-fns/format';

这是从节点包 date-fns 导入 format 函数的指令。

相关的 package.json 文件可能包含如下内容:

"scripts": {
    "start": "node app.js",
    "build-server-file": "babel app_es6.js --out-file app.js",
    "webpack": "webpack"
}

相关的 .babelrc 文件可能是这样的:

{
    "presets": [
        [
            "env",
            {
                "targets":
                {
                    "node": "current"
                }
            }
        ]
    ]
}

package.json 文件中定义的这个 build-server-file 脚本是 babel 解析 app_es6.js 文件并输出文件 app.js 的指令。

运行 build-server-file 脚本后,如果您打开 app.js 并查找 date-fns 导入,您将看到它已转换为:

var _format = require("date-fns/format");

var _format2 = _interopRequireDefault(_format);

该文件的大部分内容对大多数人来说都是 gobbledygook,但是计算机可以理解它。

另外作为参考,作为如何创建模块并将其导入项目的示例,如果您安装 date-fns,然后打开 node_modules/date-fns/get_year/index.js,您会看到它包含:

var parse = require('../parse/index.js')

function getYear (dirtyDate) {
  var date = parse(dirtyDate)
  var year = date.getFullYear()
  return year
}

module.exports = getYear

使用上面的 babel 进程,您的 app_es6.js 文件可能包含:

import getYear from 'date-fns/get_year';

// Which year is 2 July 2014?
var result = getYear(new Date(2014, 6, 2))
//=> 2014

babel 会将导入转换为:

var _get_year = require("date-fns/get_year");

var _get_year2 = _interopRequireDefault(_get_year);

并相应地处理对该函数的所有引用。


啊啊啊啊。 Babel 还没有安装在这个特定的项目上,这使得一切都有意义。我认为 ES6 导入/导出已经可以正常工作,但现在我明白 Babel 只是将所有内容都更改为 require
现在坚持要求。您将来可以随时更改它而不会出现任何问题
import won't support node_modules 你的意思是什么?
importrequire 都在 node_modules 中扫描语句指定的包。 require 将包中分配给 module.exports 的任何内容加载到分配给它的变量中,如果没有声明左手,则加载到全局范围。但是,import 将仅按名称加载 es6 默认导出,除非所有内容都分配给别名:import * as X from 'pkg'。您也可以使用 object destructuring 导入没有默认值的 es6 包:import { X } from 'pkg'。如果您将整个包(包括所有导出)导入全局范围 import 'package',它将与 require 一样工作。
s
saikiran_hegde

让我举一个例子,用 require 和 import 包含 express 模块

-要求

var express = require('express');

-进口

import * as  express from 'express';

因此,在使用上述任何语句后,我们将拥有一个名为“express”的变量。现在我们可以将“app”变量定义为,

var app = express(); 

所以我们使用 'require' 和 'CommonJS' 和 'import' 和 'ES6'。

有关“要求”和“导入”的更多信息,请阅读以下链接。

需要 - Requiring modules in Node.js: Everything you need to know

进口 - An Update on ES6 Modules in Node.js


这绝对是正确的答案。发布者在使用 es6 import 语句时遇到问题,并且对 express has no default export 错误感到困惑。这个答案提供了解决方案。具有多个(甚至单个)导出但未定义 default export 的模块将需要将所有导出分配给命名变量,如答案所述:import * as whatever from 'package';
同意,这应该是最佳答案。作为对先前评论的修正,您可以在 node_modules 中检查您所依赖的包的代码(入口点将在其 package.json main 键下列出)。 module.export = whatever 之类的内容意味着您可能必须将其作为 import * as whatever from 'package'; 导入。
J
Jeb50

我会让它变得简单,

导入和导出是 ES6 特性(下一代 JS)。

Require 是从其他文件导入代码的老式方法

主要区别在于require,整个JS文件被调用或包含。即使你不需要它的一部分。

var myObject = require('./otherFile.js'); //This JS file will be included fully.

而在导入中,您只能提取所需的对象/函数/变量。

import { getDate }from './utils.js'; 
//Here I am only pulling getDate method from the file instead of importing full file

另一个主要区别是您可以在程序中的任何位置使用 require,因为 import 应始终位于文件顶部

编辑:在最新的节点版本中,您可以使用解构。它看起来像这样

const { getDate } = require('./date.js');

您可以将对象解构与 require 一起使用,例如 const { getDate } = require('./utils.js');
是的,在我们可以使用的最新节点版本中,但在早期版本中却不是。
从版本 6(2016 年 4 月)开始,Node.js 支持解构导入。
你的整体解释太简单了,不准确。甚至关于在程序中的任何地方使用 requireimport 仅在文件顶部的声明也在掩饰重要的细节。当您使用范围为函数(或应用程序代码中某处的块范围)而不是范围为模块/文件的 require 时,这与 ES 模块(又名 import 语法)等效。虽然这是一个异步操作,但这种“动态导入”需要使用 .then()await 关键字。
require 不会“调用”或“包含”文件,它会加载并执行模块。当然,它评估模块的整个代码,而不仅仅是某个部分 - 就像 import 一样!
L
LaZza

新的 ES6:

'import' 应与 'export' 关键字一起使用,以在 js 文件之间共享变量/数组/对象:

export default myObject;

//....in another file

import myObject from './otherFile.js';

老学校:

'require' 应与 'module.exports' 一起使用

 module.exports = myObject;

//....in another file

var myObject = require('./otherFile.js');

V
Vinicius

这之间有很大的不同:

import express from "express";

和这个:

import * as express from "express";

从 CommonJS 到 ES6 的正确翻译

const express = require("express");

是第二次进口。

基本上,这是因为在第一次导入中,您正在寻找名为 express 的模块 express 中的导出。第二个是导入名称为 express 的整个 express 模块。