Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eloquent Javascript require function explanation needed

The author explains a minimal implementation of require function here that looks like:

function require(name) {
  var code = new Function("exports", readFile(name));
  var exports = {};
  code(exports);
  return exports;
}

console.log(require("weekDay").name(1));
// → Monday

I am having an hard time understanding what exactly is going on, mainly because the example is incomplete. For now, I have accepted that readFile() returns code in string format. The part that is really confusing me: why is var exports being passed into the code, what is it doing, and why is it being returned? How is exports object returning the code that readFile has retrieved?

like image 677
ApathyBear Avatar asked Sep 27 '26 09:09

ApathyBear


1 Answers

new Function("exports", body) will create an anonymous function which takes one parameter (exports) and executes the code found in body. The exports that will be passed into the function body starts as an empty object, with the intention that the module body will fill it with things it wants to expose to the rest of the world. Then the function is executed (and we pass in our exports object). Finally, the stuff that the module exported is returned.

Here is a more complete example:

fakeFileSystem = {
  "weekDay.js": "                \
      var days = [               \
        'Sunday',                \
        'Monday',                \
        'Tuesday',               \
        'Wednesday',             \
        'Thursday',              \
        'Friday',                \
        'Saturday'               \
      ];                         \
      function name(dayNo) {     \
        return days[dayNo];      \
      }                          \
      exports.name = name;       \
  "
};

function require(name) {
  var code = new Function("exports", fakeFileSystem[name + ".js"]);
  var exports = {};
  code(exports);
  return exports;
}

console.log(require("weekDay").name(1));
// → Monday

This works because code is constructed as if it was this function:

function(exports) {
  var days = [
    'Sunday',
    'Monday',
    'Tuesday',
    'Wednesday',
    'Thursday',
    'Friday',
    'Saturday'
  ];
  function name(dayNo) {
    return days[dayNo];
  }
  exports.name = name;
}

We pass {} into this function, and it will modify it to be

{
  name: function(dayNo) {
    return days[dayNo];
  }
}

where days is captured in the closure, but not visible to the outside world. This allows us to access only the things in the module that were explicitly added to exports (like name), while hiding everything that wasn't (like days).

like image 145
Amadan Avatar answered Sep 29 '26 21:09

Amadan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!