Skip to content

Instantly share code, notes, and snippets.

@MichaelrMentele
Last active August 18, 2016 21:59
Show Gist options
  • Save MichaelrMentele/eccf7ce2d511ab9b8c6b12a1d76c6434 to your computer and use it in GitHub Desktop.
Save MichaelrMentele/eccf7ce2d511ab9b8c6b12a1d76c6434 to your computer and use it in GitHub Desktop.
Lazy Objects in Javascript

Constructors

Constructors create objects in Javascript. In other languages like Ruby, or Python they are similar to classes in function.

A normal function definition in JS looks like:

    function myFunction() {}; // Semicolon optional ;)

A constructor looks like:

    function MyFunction() {}; // Capitalized by convention

What's the difference? Nothing!

Okay, cheap trick, I know. all functions are technically 'constructor functions.' The magic is in the implementation. Let's do another comparison, shall we?

A normal function will do some operation and return a value, mutate some object, or display something. We'll opt for the latter:

    function myDancingFunction() {
        console.log("Waltzing...")
    }
    // Waltzing...

Now, in contrast, a constructor function returns a new object:

    function Dancer() {
        this.firstName = "Magic"
        this.lastName = "Mike"
        this.dance = function () {
            console.log("Dirty Dancing...")
        }
        // implicitly returns an object unless you specify an explicit return
    }

    var chippendale = new Dancer() // calling the constructor...

How does it know to return an object? Only because we use the new keyword. The new keyword does some magic and basically calls the constructor with the context of an empty object to serve as what this refers to.

Calling Dancer() with new is like passing in an object and modifying it like so:

    function OtherDancer(ourNewObject) {
        ourNewObject.firstName = "Magic" 
        ourNewObject.lastName = "Mike"
        ourNewObject.dance = function() {
            console.log("Other Dirty Dancing")
        }

        return ourNewObject
    }

    var chippendale = OtherDancer({})
    // chippendale is: {firstName: "Magic", lastName: "Mike"}

So, we don't really need the new keyword at all, it's just a convenience method... Well, hold on. Maybe there are a few other thing the new keyword does for us.

It also sets the __proto__ property of our new object to the prototype object that every function references... I was going to get to prototypes I promise!

For a quick conceptual introduction (using a Star Wars analogy) of prototypes and their role in behavior delegation click HERE

Constructors and Their Prototypes

The reason we care about the __proto__ property is inheritance and defining types. Only, it's not really inheritance at all--its behavior delegation (which is one of the reasons javascript is so amazing). For more on this click the link above.

So, what if we want our dancers to get a little more classy. First, let's fix our constructor so we can pass in arguments:

    function Dancer(firstName, lastName) {
        this.firstName = firstName
        this.lastName = lastName
        //same dance method...
    }

Now, we want to create other types of dancers that reuse the above from dancer. We do that like:

    function Dancer(firstName, lastName) {  ...  }

    function NiceDancer(){
        this.classyDancing = console.log("Waltzing...")
    }
    NiceDancer.prototype = new Dancer()

Now, our NiceDancer has a prototype object that is the object literal returned by new Dancer(). If we make a call like:

NiceDancer.prototype.dance()
// prints: Dirty Dancing...
NiceDancer.prototype.classyDancing()
// prints: Waltzing...

Notice we have access through that method, and all other methods, defined on our prototype. In classical inheritance this method is copied down to 'children' in delegation objects delegate to their 'parents' and search through their parents methods when a method is called that doesn't exist on themselves.

![Lazy Behavior Delegation Chart] (https://github.com/MichaelrMentele/blog-posts/blob/master/published/constructors_are_nothing_special/prototypalInheritance.png)

Note: We could have also put the dancing method on the Dancer prototype like: Dancer.prototype.dance = function dance() {}, but the prototype of Dancer is the global object, and the global object shouldn't be able to dance!

So, a prototype is an object, linked to a constructor, so the constructor knows to pass that link to objects it creates. It does this by setting the __proto__ property on new objects.

Summary

A constructor is kind of like a recruiter, when you get hired she takes you (some roleless person) and says 'hey, you are now a software engineer and this guy is your boss.' The difference is that a constructor 'hires' new objects and says 'hey, this other object is your slave now, give it as many commands as you want and offload all your work onto it.' Which, is a brutal, but refreshing model. So, you could say that new objects are lazy because they offload work to prototype (parent) objects in a kind of reverse pyramid scheme.

Basically, JavaScript is a bossy language full of lazy children.

Yup. That pretty much sums it up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment