"require(x)"和"import x"的区别

The difference between "require(x)" and "import x"

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

正确安装了它们

例如,下面的代码抛出一个错误,告诉我 "express has no default export":

import express from "express";

但是,此代码有效:

const express = require("express");

所以我的问题是,import 和 variable/require 方法的功能有何不同?我想修复困扰我的导入的任何问题项目,因为它似乎可能会导致其他问题。

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

除此之外,

不能使用require有选择地只加载你需要的部分,但是使用import,你可以有选择地只加载你需要的部分,可以节省内存。

同步(一步一步)加载 require 另一方面 import 可以是异步的(无需等待之前的导入)所以它可以比 require.

表现的好一点

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

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

Node.js 的未来版本可能会支持 import 本身(实际上,),并且根据 Node.js' 注释判断,import 不会'不支持node_modules,基于ES6,必须指定模块路径

所以建议babel不要用import,不过这个功能还没有确认,以后可能会支持node_modules,谁知道呢?


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

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

import format from 'date-fns/format';

这是导入format function from the node package date-fns的指令。

相关的 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);

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


另外作为参考,作为如何创建模块并将其导入项目的示例,如果您安装 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);

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

让我举一个使用 require & import 包含 express 模块的例子

-要求

var express = require('express');

-进口

import * as  express from 'express';

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

var app = express(); 

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

有关 'require' 和 'import' 的更多信息,请阅读以下链接。

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

导入 - An Update on ES6 Modules in Node.js

新 ES6:

'import'要和'export'关键字一起使用,在js文件之间共享variables/arrays/objects:

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');

我会简单的,

  • 导入和导出是 ES6 特性(下一代 JS)。
  • Require 是从其他文件导入代码的老派方法

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

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

而在导入中,您只能提取需要的 objects/functions/variables。

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');

这两者有很大区别:

import express from "express";

还有这个:

import * as express from "express";

从 CommonJS 到 ES6 的正确翻译
const express = require("express");

第二个导入。

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

的整个 express 模块