You are reading a single comment by @allObjects and its replies. Click here to read the full conversation.
  • A while ago I had got pull request granted by @Gordon to enable the modules mechanisme play nicely oo... with classes... And that is how it looks like for creating a module providing, for example, a Person 'class' (The concatenated string is the source code of the 'class' definition / constructor with prototype extensions and is part of the module code):

    Modules.addCached("Person",
      'var Person = function(first, last, birthDate) {'
    + '  this.first = first;'
    + '  this.last = last;'
    + '  this.birthDate = birthDate;'
    + '};'
    + 'Person.prototype.about = function() {'
    + '  return ('
    + '    [ this.first , this.last , "is"'
    + '    , new Date().getFullYear() - this.birthDate.getFullYear()'
    + '    ,"years old."].join(" "));'
    + '};'
    + 'exports = Person;'
    );
    function onInit() {
      var Person = require("Person");
      var aPerson = new Person("Pico" , "Espruino"
        , new Date(new Date().getTime()
          - 2 * 366 * 24 * 60 * 60 * 1000)); // now - 2 years in ms
      console.log(aPerson.about());
    }
    

    On upload, you still get some warning, because the uploader does not find the module in the project / sandbox or on the Web espruino.com/modules, but when it comes to execution in the onInit(); - invocation issued as command in the console - the module - IS there... in the Modules' cache...

    How can you get rid of the warning(s)?... explained in the other conversation...

    Replace line 16 with these two lines that supply the module name in a variable and thus escape the parsing for modules before upload ...and that get's rid of the upload warning(s):

      var personClassModuleName = "Person";
      var Person = require(personClassModuleName);
    

    To work the 'proper' way of modules, place the source code into the project / sandbox / modules folder (see Espruino Web IDE setting / cog wheel in top right) as Person.js or - minified - as Person.min.js. Btw, the naming within the module is of no importance: you can make it as short as possible, for example just P for Person. It is of no importance, because the execution happens in a 'closure'.

    // Peson.js module defining Person class.
    var Person = function(first, last, birthDate) {
      this.first = first;
      this.last = last;
      this.birthDate = birthDate;
    };
    Person.prototype.about = function() {
      return (
        [ this.first , this.last , "is"
        , new Date().getFullYear() - this.birthDate.getFullYear()
        ,"years old."].join(" "));
    };
    exports = Person;
    

    and it works with the oo charm (upload this code and fire it with onInit() in the console):

    function onInit() {
      var Person = require("Person"); // get hold of class obj / constructor function
      var aPerson = new Person("Pico" , "Espruino"
        , new Date(new Date().getTime()
          - 2 * 366 * 24 * 60 * 60 * 1000)); // now - 2 years in ms
      console.log(aPerson.about());
    }
    

    Btw, you are not bound to the class name Person. You can call it what ever you want... The module loading mechanism - eval(source) - is in a closure. The module require mechanism allows a mix and match of modules where the module creators used the same name for their class definition INSIDE the module, but in the application context / namespace you can give them any (global) name of your choice, if a name at all, as shown in the next section.

    You can even be that brief (in console or code) - no need to hold on to the module / 'Class' object / Constructor (function)... and use the class obj / constructor function anonymously in your application context... just reference by the module name and delivered as object (class object / constructor function) by the module mechanism:

    new (require("Person"))("Pico","Espruino", new Date(1.4E12)).about();
    

    Output:

    ="Pico Espruino is 2 years old."
    >
    

    And if you need the Person class / constructor multiple times in various places, you can do it this way:

    var p1 = new (require("Person"))("Pico","Espruino", new Date(1.4e12));
    //...
    var p2 = new (require("Person"))("Original","Espruino­", new Date(1.375e12));
    //
    console.log(p1.about() + " -  vs. - " p2.about());
    

    I'm sure you know that the module name can also be a URL pointing to a module on the World Wide Web (with related security implications)... ;-)

    PS: Read through related using modules in modules? conversation.

About

Avatar for allObjects @allObjects started