1

I am looking here:

https://github.com/gf3/Levenshtein/blob/master/lib/levenshtein.js

I see that the code begins like this:

(function(root, factory){
  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
    define(function(){
      return factory(root);
    });
  } else if (typeof module == 'object' && module && module.exports) {
    module.exports = factory(root);
  } else {
    root.Levenshtein = factory(root);
  }
}(this, function(root){

I've never seen this before. What does it mean? What does "root" mean?

If I add this to the package.json file of my NodeJS app, then how do I use this inner function:

 // Levenshtein distance
 function Levenshtein( str_m, str_n )

All the examples use this inner function, but I don't know how to reach it.

LRK9
  • 321
  • 2
  • 4
  • 15
  • Possible duplicate of [What is 'typeof define === 'function' && define\['amd'\]' used for?](http://stackoverflow.com/questions/30953589/what-is-typeof-define-function-defineamd-used-for) – stdob-- Jan 11 '17 at 22:08
  • Just use it like normal. You may notice that it does `module.exports` as usual if it detects that it's running in node.js (module object exist) – slebetman Jan 11 '17 at 22:11

1 Answers1

1

TL;DR

What does "root" mean?

root is the first argument passed to this IIFE, which (as you see on line 11) is this. At the "top level" of a JavaScript file in Node.js, this points to the global namespace object. In the browser it points to window.

All the examples use this inner function, but I don't know how to reach it.

That's not a question, but this is how you use it in Node.js:

const Levenshtein = require('levenshtein');

const lev = new Levenshtein('bar', 'baz');
console.log(lev.distance); // => 1

What does it mean?

The purpose of all of this is to make this code work whether you use require in Node.js, an AMD module loader, or a <script> tag in the browser.

If you break it down, the code isn't too hard to understand. Let's start with the anonymous function on line 11, which is a "factory" function that just returns the Levenshtein constructor, like so:

function factory(root) {
  // ...
  function Levenshtein( str_m, str_n ) {
    // ...
  }
  // ...
  return Levenshtein
}

(In the case of the Levenshtein module, the root argument is never actually used in the "factory" function. Go figure.)

Now let's back up to the first line. Here an anonymous function is declared, which basically works like this:

function iife(root, factory) {
  const Levenshtein = factory(root);

  if (anAMDLoaderIsLoadingMe()) {
    // AMD loaders supply a `define` function
    define(function() { return Levenshtein; });
  } else if (nodeJsIsLoadingMe()) {
    // Node.js supplies the `module.exports` object
    module.exports = Levenshtein;
  } else {
    // In a browser, so `root` is `window`
    root.Levenshtein = Levenshtein;
  }
}

Finally, these two functions are used like this:

iife(this, factory);

That's it! The reason these functions are used anonymously instead of giving them sensible names like iife and factory is so that they don't clash with other functions that you might define (or that other, less well-behaved modules define). This isn't a possibility in Node.js, but it is in the browser.

Community
  • 1
  • 1
Jordan Running
  • 102,619
  • 17
  • 182
  • 182