JavaScript Prototypical Inheritance and this​

by Jedediah Smith

Who I Am

  • Jedediah Smith
  • Work for CurbNTurf
  • A book I work on off and on: JedJS.com
  • Twitter: @jedsmith13
  • LinkedIn: https://www.linkedin.com/in/jedediahsmith

What Is CurbNTurf

  • A multi-sided platform for connecting the RVer with Land Owners.
  • A young startup.
  • Written in JavaScript on the front-end and the back-end.
  • Just opened a beta and are allowing Land Owners to sign up.
  • Hiring a front-end developer.
  • Contact me if you are interested in when we open it up to guests, signing up as a host, or a job.

SR-71

SR-71

  • Top speed: 2200mph
  • 2x Pratt & Whitney J58-1 (34,000lbf Each)
  • Wingspan: 55' 7"
  • Length 107' 5"
  • Empty weight: 67,500lb
  • Loaded weight: 152,000lb
  • Introduced: 1966
  • Retired: 1999

SR-71

  • When building an aircraft as advanced as the SR-71 you start by building a prototype that you can modify and change to workout the bugs.
  • Prototypes are often built based off other similar designs.
  • Prototypes can also be used to make minor model changes.
  • Not all prototypes work out.

Arduino

Arduino

  • Has a microcontroller allowing it to be programmed
  • Inexpensive to buy
  • Numerous shields, modules, and components which can work with it.
  • Allows a huge number of possibilities
  • Used for prototyping concepts

Arduino

  • Take a base controller and add functionality
  • Easily add new functionality as desired
  • Can replace functionality if something better is needed

JavaScript's Prototypical Inheritance

  • How does it work
  • How do I use it

How Does JavaScript's Prototypical Inheritance Work

  • Chaining
  • this

Chaining

obj

{}

obj.toString()

obj.getSomething

obj.doThis()

obj.doThat()

Object

null

Parent 1

Parent 2

Parent 3

Parent 4

Parent 5

obj

{}

obj.toString()

obj.getSomething

obj.doThis()

obj.doThat()

Object

null

Parent 1

{

doThat: function

}

 

Parent 2

Parent 3

Parent 4

Parent 5

obj

{}

obj.toString()

obj.getSomething

obj.doThis()

obj.doThat()

Object

null

Parent 1

Parent 2

Parent 3

Parent 4

Parent 5

Parent 2

{

doThis: function

}

 

obj

{}

obj.toString()

obj.getSomething

obj.doThis()

obj.doThat()

Object

null

Parent 1

Parent 2

Parent 3

Parent 4

Parent 5

Parent 4

{

getSomething: 1

}

 

obj

{}

obj.toString()

obj.getSomething

obj.doThis()

obj.doThat()

Object

null

Parent 1

Parent 2

Parent 3

Parent 4

Parent 5

Object

{

toString: function

}

 

obj

{}

obj.nothing()

Object

null

Parent 1

Parent 2

Parent 3

Parent 4

Parent 5

obj

{

local: function

}

obj.local()

Object

null

Parent 1

Parent 2

Parent 3

Parent 4

Parent 5

Arduino

=

Humidity and Temperature Sensor (DHT11)

  • 1Hz Sample rate
  • 20-80% humidity range
  • 5% humidity accuracy
  • 0-50°C temperature range
  • ±2°C temperature accuracy

 

Need to measure winter temperatures in Idaho record low in Boise is  -33.33°C

Arduino

Voltage Output Temperature Sensor (TMP36)

  • -40-125°C temperature range
  • ±2°C temperature accuracy

 

Arduino

=

Humidity and Temperature sensor(s)

  • 1Hz Sample rate
  • 20-80% humidity range
  • 5% humidity accuracy
  • -40-125°C temperature range
  • ±2°C temperature accuracy

 

Need to measure winter temperatures in Idaho record low in Boise is  -33.33°C

+

What about "this"

obj

{}

obj.setName()

obj.getName()

 

Object

null

Parent 1

Parent 2

Parent 3

Parent 4

Parent 5

Parent 4

{
  setName: function (name) {
    this.name = name;
  },
  getName: function () {
    return this.name;
  }
}

With "this"

obj

{

  name: 'Me'

}

obj.setName('Me')

obj.getName()

 

Object

null

Parent 1

Parent 2

Parent 3

Parent 4

Parent 5

Parent 4

{
  setName: function (name) {
    this.name = name;
  },
  getName: function () {
    return this.name;
  }
}

With "this"

returns 'Me'

obj

{

  name: 'Me'

}

obj.setName('You')

obj.getName()

 

Object

null

Parent 1

Parent 2

Parent 3

Parent 4

Parent 5

Parent 4

var name;
{
  setName: function (newName) {
    name = newName;
  },
  getName: function () {
    return name;
  }
}

Without "this"

returns 'You'

How Do I Use JavaScript's Prototypical Inheritance

  • new
  • Object.create()
  • class

new

function Foo(a) {
    this.a = a;
    var b; //Careful with this
}

Foo.prototype.createBar = function (bar) {
    this.bar = bar;
}

Foo.prototype.setB = function (newB) {
    b = newB;
}

Foo.prototype.getB = function () {
    return b;
}

var foo = new Foo('JavaScript Prototypes');

foo.createBar('Boise Code Camp');

foo.setB('Store hidden');

foo.a; //JavaScript Prototypes
foo.bar; //Boise Code Camp

foo.b; //undefined
foo.getB(); //Store hidden

Hidden variables with new??

function Foo(a) {
    this.a = a;
    var b;
}

Foo.prototype.setB = function (newB) {
    b = newB;
}

Foo.prototype.getB = function () {
    return b;
}

var foo = new Foo('JavaScript Prototypes');

foo.setB('Store hidden');

foo.getB(); //Store hidden

var foo2 = new Foo('JavaScript Prototypes 2');

foo2.getB(); //Store hidden

foo2.setB('Store shared');

foo2.getB(); //Store shared
foo.getB(); //Store shared

Object.create()

var someObj = {
    createBar: function (bar) {
        this.bar = bar;
    }
}

var foo3 = Object.create(someObj);
foo3.a = 'JavaScript Prototypes';
foo3.createBar('Boise Code Camp');

foo3.a; //JavaScript Prototypes
foo3.bar; //Boise Code Camp

//Doesn't do what you want
var foo4 = Object.create(Foo); // Foo is really just a function

//Instead you would do
var foo5 = Object.create(foo); // foo is already an instance of Foo
//or
var foo6 = Object.create(Foo.prototype); // Foo's prototype can be used to create a function

class

class Foo {
    constructor(a) {
        this.a = a;
    }

    createBar(bar) {
        this.bar = bar;
    }

}

var foo = new Foo('JavaScript Prototypes');
foo.createBar('Boise Code Camp');

console.log(foo.a);
console.log(foo.bar);

More about 'this'

What 'this' is 'this'?

const foo = {
    a: true,
    get: function() {
        fetch('https://xkcd.com/562/info.0.json', {mode: 'no-cors'})
            .then(function(result) { 
                if (this.a) {
                    return console.log(result);
                } 
                return console.log('No this.a');
            }
        );
    }
};

const foo2 = Object.create(foo);
window.a = true;

foo2.get(); //Response
foo2.get(); // this.a doesn't exist

Object.bind()

const foo = {
    a: true,
    get: function() {
        fetch('https://xkcd.com/562/info.0.json', {mode: 'no-cors'})
            .then(function(result) { 
                if (this.a) {
                    return console.log(result);
                } 
                return console.log('No this.a');
            }.bind(this)
        );
    }
};

const foo2 = Object.create(foo);

foo2.get(); //Response

Arrow function

() => {} // ECMAScript 2015

const foo = {
    a: true,
    get: function() {
        fetch('https://xkcd.com/562/info.0.json', {mode: 'no-cors'})
            .then((result) => { 
                if (this.a) {
                    return console.log(result);
                } 
                return console.log('No this.a');
            }
        );
    }
};

const foo2 = Object.create(foo);

foo2.get(); //Response

Mixins

const fooA = {
    doA: function() {
        console.log('Consider A done');
    }
};
const fooB = {
    doB: function() {
        console.log('Consider B done');
    }
};
const fooC = {
    doC: function() {
        console.log('Consider C done');
    }
};

const foo = Object.create(fooA);

Object.assign(foo, fooB, fooC);

foo.doA(); // Consider A done
foo.doB(); // Consider B done
foo.doC(); // Consider C done

Mixins

const fooA = {
    doA: function() {
        console.log('Consider A done');
    },
    doB: function() {
        console.log('Consider A\'s version of doB done');
    }
};
const fooB = {
    doB: function() {
        console.log('Consider B done');
    }
};

const foo = Object.create(fooA);

Object.assign(foo, fooB);

foo.doA(); // Consider A done
foo.doB(); // Consider B done

Not: Consider A's version of doB done

Mixins with class

const FooA = (existingClass) => class extends existingClass {
    doA() { console.log('Consider A done'); }
};
const FooB = (existingClass) => class extends existingClass {
    doB() { console.log('Consider B done'); }
};

class Foo {
    isFoo() { return true; }
}

class FooAB extends FooA(FooB(Foo)) {
    doAB() { console.log('Sorry I am lost'); }
}

const foo = new FooAB();

foo.doA(); //Consider A done
foo.doB(); //Consider B done
foo.doAB(); //Sorry I am lost
foo.isFoo(); //true

Advantages of Using JavaScript's Prototypical Inheritance

  • Encapsulation
  • Reusable functions
  • Reduce code
  • Dynamic inheritance

JavaScript Prototypical Inheritance and this

By Jedediah Smith

JavaScript Prototypical Inheritance and this

We have all worked with prototypes in JavaScript. Maybe we have even read how to they are supposed to work. But do we really know how to use them effectively? We will cover some situations where they can be leveraged to simplify your code and then some ways to use them to make your code better.

  • 1,902