Як працює require () у node.js?


75

Я спробував це:

// 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?

Отже, я, образ, який вимагає (), може бути реалізований таким чином:

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

Це так? Будь ласка, допоможіть мені зрозуміти require (), або де я можу знайти вихідний код. Дякую!

Відповіді:


53

Вихідний код тут . exports/ - requireце не ключові слова, а глобальні змінні. Ваш основний сценарій обертається перед запуском у функцію, яка має у своєму контексті всі глобальні символи, наприклад require, processтощо.

Зверніть увагу, що хоча сам модуль.js використовує require(), це інша функція вимагати, і це визначено у файлі, який називається "node.js"

Побічний ефект вище: цілком добре мати оператор "return" в середині вашого модуля (не належить до жодної функції), ефективно "коментуючи" решту коду


Це не робить це простішим. Цей модуль використовує, requireа також визначає require. Це крок, який мені трохи важко зрозуміти, враховуючи лише вихідний код.
polkovnikov.ph

require у самому модулі - це інший require . Спрощена версія модуля створена для завантаження модульної системи - подивіться на код тут - github.com/nodejs/node/blob/v4.0.0/src/node.js#L861-L949
Андрій Сидоров

Де знаходиться документація до цієї глобальної змінної та її поверненого значення?
Шрікан

@Srikan в офіційних документах - nodejs.org/dist/latest-v8.x/docs/api/… (я не зовсім точно розумію виклик експорту / вимагаю глобальних змінних - зазвичай це аргументи функції обгортки, яка викликається коли ваш модуль завантажений)
Андрій Сидоров,

1
@AlexanderMills це не зовсім глобальна змінна, вона походить від того, що кожен модуль загортається всередину функції і requireпередається як один із аргументів цієї функції
Андрій Сидоров,

8

Андрій показав вихідний код, але якщо ви також задаєтеся питанням, як ним користуватися, тут є просте і просте пояснення ( 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);

Якщо визначити a var express = require('express'), чому після нього вони повинні перевизначити іншу змінну як var app = express()?
TomSawyer

не зрозумів, як ваш улюблений зразок пов’язаний із вимогою
ishandutta2007

@TomSawyer, оскільки require('express')повертає функцію, яка повертає програму. Це просто те, як вони його побудували. Сподіваємось, оскільки ви задали це питання 4 роки тому, ви вже відповіли на нього.
Eric Jeker

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

Функція require - це функція, яка приймає один аргумент, який називається path, у цьому випадку шлях є ./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 / внутрішня / bootstrap_node.js ), якщо так поверне модуль ще він перевіряє кількість символів в parh (Must 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 / internal / bootstrap_node.js
  8. NativeModule.wrapвиразно в Lib / внутрішньому / bootstrap_node.js приймає вміст яваскрипт скомпільований з mod.jsі загортає його: Він загортає його в якому - то іншому коді , який робить всю цю роботу. Отже, код, в який ви написали mod.js, загортається у вираз функції. це означає, що все, що ви пишете у вузлі, виконується у V8
  9. module.exports - це те, що повертається

0

Я копаю трохи більше вихідного коду 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


-9

Джерело доступне тут поруч із завантаженнями: http://nodejs.org/ export / require - це ключові слова, я не думаю, що вони закодовані безпосередньо у javascript. Вузол кодується на C ++, javascript - це просто скриптова оболонка навколо ядра C ++.


коли ви просто «думаєте» чи здогадуєтесь, краще не відповідайте на запитання. Коли модуль завантажується та аналізується з файлової системи, він обертається функцією та компілюється механізмом v8, і, нарешті, модуль кешується. require, module, __filename, І т.д., функції та змінні , що вводяться в модуль після компіляції, а модуль працює в контексті v8 двигуна, але сам модуль являє собою замикання, тому змінні і функції ніколи не конфліктували ( за винятком випадку , використовувати глобальну змінну та безлад.
Джоун Полвора,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.