Как работает require() в node.js?

Я пробовал это:

// mod.js
var a = 1;
this.b = 2;
exports.c = 3;

// test.js
var mod = require('./mod.js');
console.log(mod.a);    // undefined
console.log(mod.b);    // 2
console.log(mod.c);    // 3, so this === exports?

Итак, я представляю, что require() может быть реализована следующим образом:

var require = function (file) {
    var exports = {};
    var run = function (file) {
        // include "file" here and run
    };
    run.apply(exports, [file]);
    return exports;
}

Это правильно? Пожалуйста, помогите мне понять require() или где я могу найти исходный код. Спасибо!


person Trantor Liu    schedule 28.02.2012    source источник


Ответы (5)


Исходный код находится здесь. exports/require — это не ключевые слова, а глобальные переменные. Ваш основной скрипт обернут перед start в функции, в которой есть все глобальные переменные, такие как require, process и т.д. контекст.

Обратите внимание, что хотя сам module.js использует require(), это другая требуемая функция, и это определено в файле с именем "node.js"

Побочный эффект выше: совершенно нормально иметь оператор «return» в середине вашего модуля (не принадлежащий какой-либо функции), фактически «комментируя» остальную часть кода.

person Andrey Sidorov    schedule 28.02.2012
comment
Это не делает его проще. Этот модуль использует require, хотя он также определяет require. Это шаг, который мне немного трудно понять, учитывая только этот исходный код. - person polkovnikov.ph; 14.09.2015
comment
require в самом модуле — это другое require. Упрощенная версия модуля создана для загрузки модульной системы - посмотрите код здесь - github.com/nodejs/node/blob/v4.0.0/src/node.js#L861-L949 - person Andrey Sidorov; 14.09.2015
comment
Где документация для этой глобальной переменной и ее возвращаемого значения? - person Srikan; 02.06.2017
comment
@Srikan в официальных документах — nodejs.org/dist/ last-v8.x/docs/api/ (я не совсем прав в отношении вызова глобальных переменных exports/require — обычно они являются аргументами функции-оболочки, которая вызывается при загрузке вашего модуля) - person Andrey Sidorov; 02.06.2017
comment
require не является глобальной переменной tmk, она привязана к __dirpath текущего файла и т. д. - person Alexander Mills; 26.06.2018
comment
@AlexanderMills это не совсем глобальная переменная, это происходит из-за того, что каждый модуль заключен в функцию, и require передается как один из аргументов этой функции. - person Andrey Sidorov; 27.06.2018

Андрей показал исходный код, но если вам также интересно, как его использовать, легкое и простое объяснение здесь ( http://nodejs.org/api/modules.html).

Это были два хороших примера для меня.

//foo.js, multiple methods
var circle = require('./circle.js');
console.log( 'The area of a circle of radius 4 is ' + circle.area(4));

//circle.js
var PI = Math.PI;
exports.area = function (r) {
  return PI * r * r;
};
exports.circumference = function (r) {
  return 2 * PI * r;
};

//bar.js
var square = require('./square.js');
var mySquare = square(2);
console.log('The area of my square is ' + mySquare.area());

//square.js, single method
module.exports = function(width) {
  return {
    area: function() {
      return width * width;
    }
  };
}

Мой любимый узор

(function (controller) {

  controller.init = function (app) {

    app.get("/", function (req, res) {
        res.render("index", {});
    });

  };
})(module.exports);
person Andy    schedule 24.12.2014
comment
Если определить var express = require('express'), почему после этого они должны переопределить другую переменную как var app = express()? - person TomSawyer; 12.08.2016
comment
не понял, как ваш любимый шаблон связан с require - person ishandutta2007; 25.03.2017
comment
@TomSawyer, потому что require('express') возвращает функцию, которая возвращает приложение. Это просто то, как они это построили. Надеюсь, поскольку вы задали этот вопрос 4 года назад, вы уже ответили на него. - person Eric Jeker; 07.07.2020

var mod = require('./mod.js');

Требование — это функция, которая принимает один аргумент, называемый путем, в данном случае путь равен ./mod.js.

когда вызывается требование, происходит последовательность задач:

  1. вызвать Module.prototype.require функцию, объявленную в lib/module.js, которая утверждает, что путь существует и был строкой

  2. вызовите Module._load, который является функцией в lib/module.js, которая разрешить файл через Module._resolveFilename(request, parent, isMain),

  3. вызывается функция Module._resolveFilename и проверяет, является ли модуль родным (собственные модули возвращаются функцией NativeModule, определенной в lib/internal/bootstrap_node.js), если да, он вернет модуль, иначе он проверит количество символов parh (не менее 2 символов) и некоторые символы (символ путь должен начинаться с ./) через функцию Module._resolveLookupPaths, определенную в lib/internal/bootstrap_node.js
  4. проверьте каталог, в котором находится файл
  5. Если путь содержит расширение (в нашем примере да: mod.js), функция базового имени, определенная в lib/path.js проверяет, что расширение "js"
  6. затем он создаст новый модуль для файла, указанного в аргументе var module = new Module(filename, parent);
  7. контент будет скомпилирован через v8 через функцию NativeModule.prototype.compile, определенную в lib/ внутренний/bootstrap_node.js
  8. NativeModule.wrap, определенный в lib/internal/bootstrap_node.js берет содержимое javascript, скомпилированное из mod.js, и оборачивает его: он оборачивает его в какой-то другой код, который заставляет все это работать. Таким образом, код, который вы написали в mod.js, заключен в функциональное выражение. это означает, что все, что вы пишете в узле, запускается в V8
  9. модуль.экспорт - это то, что возвращается
person Mohamed Ben HEnda    schedule 24.10.2017

Я копаю еще немного исходного кода nodejs/2/ и делаю диаграмму последовательности/1/, надеюсь, это даст вам интуитивно понятный обзор. Есть еще одна статья http://fredkschott.com/post/2014/06/require-and-the-module-system/, которые также объясняют механизм require() простым способом, сначала прочитайте эту статью, это поможет вам быстро понять схему. введите здесь описание изображения

Ссылка:

/1/ исходный репозиторий диаграммы: https://github.com/z1yuan/nodejs.git

/2/ https://github.com/nodejs/node-v0.x-archive.git

person Zhi Yuan    schedule 27.09.2019

Источник доступен здесь рядом с загрузками: http://nodejs.org/ exports/require являются ключевыми словами, я не не думаю, что они закодированы в javascript напрямую. Node написан на C++, а javascript — это просто скриптовая оболочка вокруг ядра C++.

person mpm    schedule 28.02.2012
comment
когда просто думаешь или догадываешься, лучше не отвечай на вопросы. Когда модуль загружается и анализируется из файловой системы, он оборачивается в функцию и компилируется движком v8, и, наконец, модуль кэшируется. require, module, __filename и т. д. — это функции и переменные, введенные в модуль после компиляции, и модуль работает в контексте движка v8, но сам модуль является замыканием, поэтому переменные и функции никогда не конфликтуют (за исключением случая, когда вы используете глобальная переменная и беспорядок. - person Jone Polvora; 04.07.2019