Javascript Notebook
  • Introduction
  • Intro to JavaScript
    • Section 1 - Getting Started
    • Section 2 - Execution Contexts and Lexical Environements
    • Section 3 - Types and Operators
    • Section 3 Part 2 - Closures and Callbacks
    • Section 4 - Objects and Functions
    • Section 5 - Object Oriented Javascript and Prototypal Inheritance
    • Section 6 - Building Objects
    • Section 7 - Odds and Ends
    • Section 8 - Examining Famous Frameworks and Libraries
    • Section 9 - Let's Build a Framework or Library!
  • Midterm Review
  • Final Review
  • jQuery
    • Section 1 - Selectors
    • Section 2 - Events
    • Section 3 - Effects
  • Node.js
    • The Node Core
    • Modules, Exports, and Require
    • Events and the Event Emitter
    • Databases and SQl
  • D3.js
    • Diving In
    • Bar Chart
    • Creating A Complex Bar Chart
Powered by GitBook
On this page
  • History, Function Constructors, and 'new'
  • Function Constructor and Prototype
  • Built-in Function Constructors
  • Objects.create and Pure Prototypal Inheritance
  • Inheritance: (personally) a better approach
  • ES6 and Classes

Was this helpful?

  1. Intro to JavaScript

Section 5 - Object Oriented Javascript and Prototypal Inheritance

History, Function Constructors, and 'new'

  • Javascript was named the way it was because the original developers wanted to attract developers from java.

    • A form of marketing.

    • Even though it was nothing like java.

  • Lets take a look on the few different ways we've learned to construct objects.

  • Method 1

    var person = {
        first: 'dan',
        last: 'mak'
    }
    console.log(person);
  • Method 2

    var person2 = new Object();
    person2.first = 'sam';
    person2.last = 'mak';
    console.log(person2);
  • Method 3 (new method)

    var person3 = function() {
        this.first = 'dav',
        this.last = 'mak'
    }
    person3_log = new person3();
    console.log(person3_log);
  • How the new keyword works

    • Creates a new empty object (person), whose 'this' contains nothing.

    • Then the properties are supplied to 'this'

    • The new object becomes returned

  • Make a dynamic constructor (preferred way):

    var personConstructor = function(first, last) {
        this.firstName = first;
        this.lastName = last;
    }

    var dan = new personConstructor('dan', 'mak');
    console.log(dan);
  • Even though js does not have classes, personConstructor can behave similar to one.

Function Constructor and Prototype

  • Now lets discuss how inheritance works.

    var personConstructor = function(first, last) {
        this.firstName = first;
        this.lastName = last;
    }

    personConstructor.prototype.getFullName = function() {
        return this.firstName + ' ' + this.lastName;
    }

    var dan = new personConstructor('dan', 'mak');
    console.log(dan.getFullName()); // dan mak
  • prototype is a keyword that is specifically used with function constructors.

  • Its like extending the definition of an object.

  • It can be helpful because every unique object will have access to their inherited prototype.

    • Still I'd recommend ec6 classes over prototypes.

    var sam = new personConstructor('sam', 'mak');
    console.log(sam.getFullName()); //sam mak



    ...

    personConstructor.prototype.getFormalFullName = function() {
        return this.lastName + ' ' + this.firstName;
    }


    var dan = new personConstructor('dan', 'mak');
    console.log(dan.getFullName()); //dan mak
    console.log(dan.getFormalFullName());// mak dan
  • The neat thing about this is that regardless of how many objects we have, we can define a property for all of those objects very quickly.

  • You may think that it is just as effective to place getFullName() to the function constructor.

    • You are correct in that this will work, but its not exactly as effective.

    • We have to remember that the objects we construct exist in memory, and if we had a million objects, each object would have all the properties we've defined it have.

  • Sigh... thinking back to my earlier C++ projects, I've made so many mistakes without this idea.

  • We dont want to waste memory space for something that is not-unique.

    • Afterall, getFullName() references a static element of that object. Why would we want to create the same method for each object?

    • getFullName() references elements from the object that are unique.

      • So it would make sense to define the firstname and lastname in the constructor.

  • This is why in general we define methods in the prototype.

  • Its like class definitions in C++.

    • We dont construct a object with function defintions, that would be absurd. Instead, we define methods in the class, that each object has assess from. What we construct the object with are essentially uniquely defined variables that resonate with its class.

  • There is a convention used with function constructors. Begin the name with a capital letter, as a reminder for yourself to use the new keyword.

Built-in Function Constructors

  • The js engine also has some neat ways of creating new objects with in-built functions.

    var objectNumber = new Number(3);
    var stringNumber = new String('eyman');
    var data = new Data('3/2/2013'); 
  • And the result creates an object with a lot of neat properties. String, for example, automate this procedure.

    String {0: "e", 1: "y", 2: "m", 3: "a", 4: "n", length: 5, [[PrimitiveValue]]: "eyman"}
  • We can also explore each functions prototype methods as well.

  • Now, like before, we can extend our own prototype methods to this inbuilt function, just like any other object.

    String.prototype.isGreaterThan = function(limit) {
        return this.length > limit;
    }

    console.log("Daniel".isGreaterThan(3)); // true
  • 'this' points to the object String, and prototype extends its definition with a function we've defined for ourselves.

  • .length is an inbuilt function (shown before)

  • Another example:

    var a = new Number(3);

    Number.prototype.isPositive = function() {
        return this > 0;
    }

    console.log(a.isPositive()); //true
  • Notice that a is an object. It is not a number, even though it looks like a primitive form.

  • this directly points to the object in Number.

  • Side note: It is generally not recommended to use function constructors, because it can get messy. Why? Because we've complicating the whole primative vs nonprimitive thing.

    var a = 3;
    var b = new Number(3);

    a == b // true -> coersion
    a === b // false -> different type return
  • As a side note, arrays act a little different as objects.

    var array = ['a', 'b', 'c'];

    for (var prop in array){
        console.log(prop + ': ' + array[prop]);
    }


    //output
    0: a
    1: b
    2: c
  • The indexs are actually just properties of the array.

  • That means if we were not modified its Object form, things can get messy.

    var array = ['a', 'b', 'c'];
    Array.prototype.getIntheWay = 'bad';

    for (var prop in array){
        console.log(prop + ': ' + array[prop]);
    }
  • The properties may not print out as you might expect them to.

  • Further more, now that we know how the properties are created, it explains why we're able to navigate through the array object like this.

    for (var i = 0; i < array.length; i++) {
        console.log(i + ': ' + array[i]);
    }

Objects.create and Pure Prototypal Inheritance

  • Objects.create is yet another way to construct new objects

    var person = {
        first: 'default',
        last: 'default',
        greet: function() {
            return "Hi " + this.first;
        }
    }


    var John = Object.create(person); // pure prototypal inheritance
    console.log(John); // see below
    console.log(John.greet()); // Hi default


    Object {}
    __proto__: Object
    first: "default"
    greet: ()
    last: "default"
    __proto__: Object
  • Object.create constructs a new Object, but it is not the immediate object. Nothing gets overwritten either.

  • Instead, its creates a NEW empty objects whose prototype is a copy of the object passed in.

  • The idea here is that we can overwrite whatever properties we want.

    John.first = 'John';
    console.log(John.first); // John
  • Also notice that John.first writes to the immediate empty object. The prototype stays as it was initially.

  • The key here is that the prototype remains as only a single copy.

  • This is quite useful because the methods are essentially inherited.

    console.log(John.greet());// Hi John
  • Sometimes, it is necessary to create whats known as a polyfil. Not all browsers support Object.create, as it is a reletively new in modern browsers. Lets write our own Objects.create()

    if (!Object.create) {
        Object.create = function(o){
            if (arguments.length > 1) {
                throw new Error("Objects.create accepts one 1 parameter");
            }
            function F() {};
            F.prototype = o;
            return new F();
        }
    }
  • What we know about object.create:

    • A new empty object is created -> function f() {};

    • The empty object prototype points to and copies the arguments of the objects passed in.

Inheritance: (personally) a better approach

var Person = {
    firstname: '',
    lastname: '',
    greet: function() {
        return this.firstname + ' ' + this.lastname;
    }
}

var dan = Object.create(Person);
dan.firstname = 'dan';
dan.lastname = 'mak';

var dav = Object.create(Person);
dav.firstname = 'dav';
dav.lastname = 'mak';

console.log(dan.greet());
console.log(dav.greet());

ES6 and Classes

  • ES6 is now released an supported as of June 2015.

  • Introduces classes

    "use strict";
    class Person {
        constructor(first, last) {
            this.firstname = first;
            this.lastname = last;
        }

        greet() {
            return 'hi ' + this.firstname; 
        }
    }

    var person = new Person('dan', 'mak');
    console.log(person.greet()); //hi dan
  • Pretty cool, coming from a C++ background

  • Notice that the browser currently requires declarations used in 'strict mode';

  • Because ES6 is not wildly supported yet, it is still recommend to stick with ES5 - especially if your using implementations from different js libraries like moments.js, underscore.js, etc.

    • Because it may take some time to update this libraries to support the new changes.

  • Classes are OBJECTS TOO!

    • That means we can use and modify them as objects.

  • Inheritance with classes:

    class InformalPerson extends Person {
        constructor(first, last) {
            super(first, last);
        }

        greet() {
            return 'yo ' + first;
        }
    }
  • We've learned many ways of constructing an object.

  • Syntactic sugar, is a word thrown around when their is a different way to write something, but the way it works under the hood is not changed.

PreviousSection 4 - Objects and FunctionsNextSection 6 - Building Objects

Last updated 5 years ago

Was this helpful?