Skip to content

Instantly share code, notes, and snippets.

@chadfurman
Last active February 10, 2017 07:41
Show Gist options
  • Select an option

  • Save chadfurman/258ee2db719b8e781e864e0cfa56a29d to your computer and use it in GitHub Desktop.

Select an option

Save chadfurman/258ee2db719b8e781e864e0cfa56a29d to your computer and use it in GitHub Desktop.
h6

Inheritance

  • Prototypal Inheritance is not Inheritance -- Inheritance is for class-based languages
  • Prototypal Inheritance is completely opposite of regular Inheritance
  • When we create an object with Prototypes, the new object links "up" the prototype chain.
  • In regular inheritance, we have a "parent" class and the Inheritance flows downward.
  • Inheritance is "copy down", Prototypal is "delegate up"
  • All OO in JS is an attempt to make Prototype Inheritance work like Class Inheritance
  • We should instead consider JS as having Behavior Delegation, which is a design pattern.

OLOO

  • Let's simplify JS "inheritance" into "Behavior Delegation"
  • OLOO -- Objects Linked to Other Objects
function Foo(who) {
  this.me = who;
}
Foo.prototype.identify = function() {
  return "I am " + this.me;
};

function Bar(who) {
  Foo.call(this, who);
}
Bar.prototype = Object.create(Foo.prototype);

Bar.prototype.speak = function() {
  alert("Hello, " + this.identify() + ".");
};

var b1 = new Bar("b1");
b1.speak(); // alerts "Hello, I am b1."
  • The only thing that matters here is the b1 -> Bar.prototype -> Foo.prototype linkage
  • So how do we get from here to OLOO?
  • Let's take a couple of steps -- pay attention only to b1, Bar.prototype, and Foo.prototype.
  • The first step is to get rid of any Class-oriented thinking (i.e. new)
function Foo(who) {
  this.me = who;
}
Foo.prototype.identify = function() {
  return "I am " + this.me;
};

function Bar(who) {
  Foo.call(this, who);
}
Bar.prototype = Object.create(Foo.prototype);

Bar.prototype.speak = function() {
  alert("Hello, " + this.identify() + ".");
};

var b1 = Object.create(Bar.prototype);
Bar.call(b1, "b1");
b1.speak();
  • Now we use object.create() to link b1 to Bar.prototype. We now have to call Bar with b1 as the "this" property: i.e. Bar.call(b1, "b1");
  • We still have b1 -> Bar.prototype -> Foo.prototype
  • Now the next step is to get rid of any reference to .prototype because it's confusing
function Foo(who) {
  this.me = who;
}
Foo.prototype.identify = function() {
  return "I am " + this.me;
};

var Bar = Object.create(Foo.prototype);
Bar.init = function(who) {
  Foo.call(this, who);
};
Bar.speak = function() {
  alert("Hello, " + this.identify() + ".");
};

var b1 = Object.create(Bar);
b1.init("b1");
b1.speak();
  • Now we just link b1 directly to bar. We use Object.create() to perform all our links.
  • We still have b1 -> Bar -> Foo.prototype
  • We still need to get rid of all the references to Foo.prototype and the function Foo constructor
var Foo = {
  init: function(who) {
    this.me = who;
  },
  identify: function() {
    return "I am " + this.me;
  }
};

var Bar = Object.create(Foo);

Bar.speak = function() {
  alert("Hello, " + this .identify() + ".");
};

var b1 = Object.create(Bar);
b1.init("b1");
b1.speak(); // alert: "Hello, I am b1."
  • An example would be Foo as a Utility object with loggers etc that other objects delegate to

OLOO Questions

  • What if you want to delegate b1 to more than one object?

    • There's only one prototype chain.
  • What if you wanted a constructor?

    • You could have one. Bar had an "init" function. We just moved it to Foo.
    • If you want to have multiple objects with the same method, you have to do manual explicit polymorpishm which is silly
    • Instead, you give them different method names like findUser and findTask vs just find
  • No more constructors?

    • If we need to do init tasks, we can add a function to init
    • with new you were forced to do construction and init at the same time, this way you have flexibility to construct first and init at another time
  • Is there a performance concern because we don't have prototypes anymore?

    • This is the exact same as having prototypes, it has the same performance characteristics
    • If you have b1 through b1000, they would each only have the me property
  • Are there real world examples of OLOO?

    • This is something Kyle invented and he's still trying to convince the world to stop making classes
  • Will you show us Object.create()?

    • Yes, in a second :)
  • What's the main contention point?

    • The primary push-back is that "Classes are how we were taught to design things"
    • Class design is an option, delegation is another option
    • Delegation goes with the flow of how JS actually works
  • How does Object.create() work?

if (!Object.create) {
  Object.create = function (o) {
    function F() {}
    F.prototype = o
    return new F();
  };
}

Quiz: Prototypes

  1. How is JavaScript's [[Prototype]] chain not like traditional/classical inheritance?
  • It doesn't copy. It "delegates" up rather than copying down.
  1. What does "behavior delegation" mean and how does it describe object linking in JS?
  • A new object delegates up the prototype chain to another object.
  1. Why is "behavior delegation" as a design pattern a helpful thing? What are the tradeoffs?
  • You don't have copies of the functions
  • With delegation, we are embracing the fact that objects continue to exist and are dynamically changing
  • With classes, it's a snapshot -- once we've made the copy, if the parent changes the childs don't.
  • Delegation is more powerful than classes because you can implement classes in delegation but you can't do the reverse
  • One of the tradeoffs is that "shadowing" (having methods with the same name) is awkward
  • Another tradeoff is that everything is public. You lose all the benefits of encapsulation

95% of the time, we use module pattern because we normally only want a few instances.

Exercise 4

  • Create a widget and a button as a "parent" and "child"
  • 1st, use the prototype style
  • 2nd, use the OLOO style
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment