• Design
  • Shotty
  • Blog
  • Reading
  • Photos
Menu

Jacob Ruiz

Product Designer
  • Design
  • Shotty
  • Blog
  • Reading
  • Photos
librarySystem2@2x.png

Mastering Javascript Fundamentals: LibrarySystem (Part 2)

April 30, 2018

Get the fundamentals down and the level of everything you do will rise. - Michael Jordan

Continuing on day 4 of posting my notes on this this blog as I learn to master Javascript fundamentals one day at a time.

As stated in my original post, I do 1 hour of video lessons from Watch and Code every day. If you're interested in learning Javascript in a way that goes beyond basic tutorials and gives you a foundational, practical knowledge without relying on frameworks - I'd highly recommend it. If you're reading these posts, please keep in mind that these are just my notes, and I'm not an expert (yet!). If your goal is also to master the fundamentals of Javascript, please head over to Watch and Code and start your journey there!


This is part 2 about librarySystem. For part 1, please click here.

LibrarySystem Part 2

Here is a side by side comparison of the two approaches:

Screen Shot 2018-05-01 at 9.52.14 AM.png

In the new system, on line 20, we say "hey librarySystem, go get me the sandwichLibrary".

Arguably the approach on the left is a little bit nicer when using the library, but you need to get used to both.

For example in NodeJS, you'll use require, which is a lot like the right side approach.

So lets say you're the library author - you have this real problem that developers might use the left side approach, or the right side approach - you don't know.

One solution: I'll just have two versions (the left and the right). But this isn't good because you'd have to make the same changes in each every time you update.

The best solution would be to just have one file, and it just dynamically does the right thing depending on what's available.

For example, you could use logic such as: if the librarySystem is defined, use the approach on the right side, if not - use the approach on the left.

So how would you do something like that?

Well, let's naively try to do both:

(function() {
    var breads = {
      wheat: 'The healthy option',
      white: 'The unhealthy option'
    };
    var fillings = {
        turkey: 'For boring sandwiches',
        cheese: 'For the vegetarians'
    };
    var sandwichLibrary = {
        breads: breads,
        fillings: fillings
    };

    // Handle window case.
    window.sandwichLibrary = sandwichLibrary;

    // Handle librarySystem case.
    librarySystem('sandwichLibrary', function() {
      return sandwichLibrary;
    });

})();

This is a  good start, but it's kind of dumb. It's not dynamically choosing the right thing.

A smarter way is to put these in an if/else statement to choose between the two cases. Something like this:

(function() {
    var breads = {
      wheat: 'The healthy option',
      white: 'The unhealthy option'
    };
    var fillings = {
        turkey: 'For boring sandwiches',
        cheese: 'For the vegetarians'
    };
    var sandwichLibrary = {
        breads: breads,
        fillings: fillings
    };

    // Handle window case.
    window.sandwichLibrary = sandwichLibrary;

    if (/* librarySystem function exists */) {
      // Handle librarySystem case.
      librarySystem('sandwichLibrary', function() {
        return sandwichLibrary;
      });
    } else {
      // Handle window case.
      window.sandwichLibrary = sandwichLibrary;      
    }

})();

The last thing we need to do is get the if condition to work.

Specifically, we need to know if librarySystem is undefined, because then we know we're in an environment where the developer is not using a librarySystem.

The way we do this in javascript is a little clunky.

We need to get the type of the librarySystem variable.

Let's go to the console and see what that means.

There's a keyword typeof that gives you the type of whatever you give it.

Screen Shot 2018-05-01 at 10.18.28 AM.png

So we want to use this check to see whether or not the librarySystem function is undefined.

Screen Shot 2018-05-01 at 10.20.32 AM.png

So on a new page, this is undefined.

But if we define it:

Screen Shot 2018-05-01 at 10.21.45 AM.png

Then we check the type, we see that it's a function:

Screen Shot 2018-05-01 at 10.23.17 AM.png

So we want to see: librarySystem defined? If it is, we'll use that method. If it isn't defined, then we won't use it.

Using what we know now, let's add the logic to the if statement:

(function() {
    var breads = {
      wheat: 'The healthy option',
      white: 'The unhealthy option'
    };
    var fillings = {
        turkey: 'For boring sandwiches',
        cheese: 'For the vegetarians'
    };
    var sandwichLibrary = {
        breads: breads,
        fillings: fillings
    };

    // Handle window case.
    window.sandwichLibrary = sandwichLibrary;

    // if librarySystem is undefined
    if (typeof librarySystem !== 'undefined') {
      // Handle librarySystem case.
      librarySystem('sandwichLibrary', function() {
        return sandwichLibrary;
      });
    } else {
      // Handle window case.
      window.sandwichLibrary = sandwichLibrary;      
    }

})();

And that's pretty much it.

It's the same library code as before. We have our breads, fillings, and we're creating our sandwichLibrary object.

If librarySystem exists, then we:

  • Call librarySystem
  • Give librarySystem the name of the library ('sandwichLibrary').
  • Give it a function that returns the 'sandwichLibrary' library object.


If librarySystem doesn't exist, then we:

  • Attach the sandwichLibrary object to the window, and create a global variable.

Now your library will dynamically do the right thing.

This is the approach that accountingJS takes, and pretty much every other open source javascript library.

Let's use what we've made so far by putting this code in the console and putting a debugger statement in above our if/else check to see if librarySystem is undefined.

Screen Shot 2018-05-01 at 10.33.15 AM.png

Since we've just refreshed the page, librarySystem doesn't exist, and we skip over the if case, and go directly to line 26:

Screen Shot 2018-05-01 at 10.35.32 AM.png

This line attaches sandwichLibrary to the window object.

There's no return value:

Screen Shot 2018-05-01 at 10.37.46 AM-annotated.png

We can now access sandwichLibrary globally:

Screen Shot 2018-05-01 at 10.39.35 AM.png

In this case we went into the else statement because librarySystem didn't exist. But what if it does exist?

Screen Shot 2018-05-01 at 10.45.26 AM.png

Let's paste in our new code with the if/else statement that checks to see if librarySystem is undefined, and add a debugger statement again:

Screen Shot 2018-05-01 at 10.46.44 AM.png

This time, librarySystem does exist.

Screen Shot 2018-05-01 at 10.48.21 AM.png

When we go into librarySystem, we see that libraryName is 'sandwichLibrary':

Screen Shot 2018-05-01 at 10.50.32 AM.png

Since we have more than one argument, we go into the "create" section of the code:

Screen Shot 2018-05-01 at 10.51.41 AM.png

Here we create a new property on the libraryStorage object, called 'sandwichLibrary', and it's going to be equal to the return value of our callback function.

Remember that all our callback function does is return the sandwichLibrary.

Screen Shot 2018-05-01 at 10.54.19 AM.png

By the time the librarySystem function has finished running, we can see that the libraryStorage object now contains the sandwichLibrary object.

Screen Shot 2018-05-01 at 10.58.41 AM.png

That's in for Part 2. In Part 3, we'll look at how Accounting JS handles this.

Summary

  • When building a library, we don’t know if the developer prefers to create a global variable on the window object for every library, or use librarySystem.
  • To solve this, we can create an if/else statement that checks to see if librarySystem exists. 
  • If librarySystem exists, we call the librarySystem function.
  • If librarySystem doesn’t exist, we attach sandwichLibrary directly to the window object.

 

 

← Reading: "Remote: Office Not Required" by Jason Fried of 37signalsMastering Javascript Fundamentals: librarySystem (Part 1) →
shotty-skinny2x.jpg

Shotty - Faster Access To Your Screenshots on Mac

Shotty is an award-winning Mac app I created to give you instant access to all your recent screenshots, right from the menu bar. You can even add annotations on-the-fly. Stop wasting time digging through Finder for your screenshots. I promise it’ll change your workflow forever (just read the App Store reviews!).



Most popular

information-architecture

Information Architecture: The Most Important Part of Design You're Probably Overlooking

Follow @JacobRuizDesign