Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Object Oriented JavaScript

Object Oriented JavaScript

Slides from a talk I gave at a joint Meetup with Santa Barbara JavaScript and Learn to Code Santa Barbara, 5/3/2016

Tim Doherty

May 03, 2016
Tweet

More Decks by Tim Doherty

Other Decks in Technology

Transcript

  1. What is OOP? “OOP to me means only messaging, local

    retention and protection and hiding of state- process, and extreme late-binding of all things. It can be done in Smalltalk and in LISP. There are possibly other systems in which this is possible, but I'm not aware of them.” 1 ~ Dr. Alan Kay 1. In a 2003 letter to Stefan Ram
  2. What is OOP? JavaScript is a multi-paradigm language • Imperative

    (procedural) • Object oriented • Functional It’s possible to program purely in one paradigm, but a hybrid style is more typical In the sense that everything except primitives is an object, JavaScript is more object- oriented than many mainstream OO languages
  3. What is an Object? In JavaScript, the concept of objects

    is minimalist: • Objects are simple dictionaries of key/value pairs • Properties and methods can be added and removed at runtime • Objects can directly manipulate each other’s state • Constructors are optional • Prototypes are optional
  4. Object Literals Objects can be created without constructors or prototypes,

    using object literal notation var obj = { foo: 'bar', bar: function () { return 'baz'; }, ['b' + 'a' + 'z']: 'bim', bim() { return 'bam'; } };
  5. Constructors Constructors can be used to couple instantiation and initialization

    of objects • Constructors are optional, there is no default constructor • Constructors are just functions, with no special syntax or ceremony 1 • Must be invoked with “new” keyword to create objects 1. The JavaScript community has embraced the convention of capitalizing constructor names
  6. Prototypes JavaScript is a prototype-based language. Instead of classes, it

    has prototypes. 1 A prototype is just an object, to which behavior is delegated by another object • Prototypes are optional 2 • Changes to a prototype affect instances created from them 1. ECMAScript 2015 (ES6) introduces class syntax, but it is unrelated to class-based OOP 2. By default, objects have the built-in Object object as their prototype
  7. Prototypes function MyObj() { this.foo = 'bar'; } MyObj.prototype.bar =

    function () { return 'this.foo: ' + this.foo; }; myObj = new MyObj(); myObj.foo // 'bar' myObj.bar() // 'this.foo: bar'
  8. Prototypes MyObj.prototype.baz = function () { return this.foo + '

    has baz() now'; }; myObj.baz(); // 'bar has baz() now'
  9. Object.create Objects can be created, with or without prototypes, using

    Object.create() var obj = Object.create(undefined); var obj = Object.create(undefined, { foo: { value: 'bar' } }); var obj = Object.create({ foo: 'bar' }); var obj = Object.create({ foo: 'bar' }, { bar: { value: 'baz'} });
  10. Object Factory function myObjFactory(props) { var myObjProto = { foo:

    () => 'bar', bar: () => 'baz' }; return Object.create(myObjProto, props); } var newObj = myObjFactory({ baz: { value: () => 'bim' } }); newObj.foo(); // 'bar' newObj.bar(); // 'baz' newObj.baz(); // 'bim'
  11. Hybrid Approach function MyObj() { this.foo = 'bar'; } MyObj.prototype.bar

    = () => 'baz'; var obj = Object.create(MyObj.prototype, { baz: { value: 'bim' } }); MyObj.call(obj); obj.foo; // 'bar' obj.bar(); // 'baz' obj.baz; // 'bim'
  12. Classes Classes were introduced in ECMAScript 2015 (ES6) and are

    a controversial feature. Classes are just syntactic sugar atop constructors and prototype chains Pros: • Syntax is initially friendlier to class-based OO developers • Standardization makes tooling simpler Cons: • Syntax is very different from underlying semantics • Mismatch confuses very same class-based OO developers
  13. Classes class MyObj { constructor() { this.foo = 'bar'; }

    bar() { return 'this.foo: ' + this.foo; } } myObj = new MyObj(); myObj.foo // 'bar' myObj.bar() // 'this.foo: bar'
  14. Property Access Properties and methods can be accessed by dot

    or bracket notation, the latter of which allows computed property access: obj.foo; // 'bar obj['foo']; // 'bar' obj[['f','o','o'].join('')]; // 'bar'
  15. What’s this? “Sometimes when I'm writing Javascript I want to

    throw up my hands and say "this is bullshit!" but I can never remember what "this" refers to” Ben Halpern @bendhalpern
  16. What’s this? The value of “this” changes depending on context.

    Seems crazy, but it’s what makes prototypal OO work, and it allows objects to “borrow” behavior from other objects. var obj1 = { name: 'foo', speak: () => 'My name is ' + this.name }; var obj2 = { name: 'bar' }; obj1.speak.call(obj2); // 'My name is bar'
  17. Encapsulation JavaScript has no concept of access modifiers, by default

    everything is public, but there are strategies for achieving encapsulation: • Closures / privileged methods • Symbols
  18. Encapsulation with Closures var obj = (() => { var

    foo = 'bar'; return { get foo() { return foo; }, set foo(val) { foo = val; } }; })(); obj.foo; // 'bar' obj.foo = 'baz'; obj.foo; // 'baz'
  19. Encapsulation with Closures function MyObj() { var foo = 'bar';

    this.getFoo = () => foo; this.setFoo = (val) => { foo = val; }; } var obj = new MyObj(); obj.getFoo; // 'bar' obj.setFoo('baz'); obj.getFoo; // 'baz'
  20. Encapsulation with Symbols var MyObj = (function () { var

    fooSymbol = Symbol(); return class MyObj { constructor(foo) { this[fooSymbol] = foo; } get foo() { return this[fooSymbol]; } }; })(); var obj = new MyObj('bar'); obj.foo; // 'bar'
  21. Inheritance JavaScript supports two distinct types of inheritance: • Prototypal:

    behavior is delegated up a prototype chain • Concatenative: behavior is copied from another object(s)
  22. Prototypal Inheritance JavaScript emulates class-based inheritance with behavior delegation. Behavior

    is delegated up a prototype chain until an implementation is found. • If an object has the method, invoke it • If an object doesn’t have the method, check its prototype • If the object has a prototype, and the prototype has the method, invoke it • Rinse and repeat until the top of the chain (Object.prototype) • If the chain ends without an implementation, an exception occurs
  23. Prototypal Inheritance function MyObj() {} MyObj.prototype.foo = () => 'bar';

    function YourObj() {} YourObj.prototype = new MyObj(); var obj = new YourObj(); obj.foo(); // 'bar' obj.baz(); // Error
  24. Concatenative Inheritance Concatenative inheritance involves combining the properties of one

    or more source objects into a new destination object. • Dynamic extension of objects • Popularized by $.extend() and _.extend() • Supported natively with Object.assign() • Enables multiple inheritance
  25. Concatenative Inheritance var obj1 = { foo() { return 'bar';

    } }; var obj2 = { bar() { return 'baz'; } }; var obj3 = Object.assign({}, obj1, obj2); obj3.foo(); // 'bar' obj3.bar(); // 'baz'
  26. Polymorphism - Overriding Methods can be “overridden” or - since

    JavaScript is a weakly-typed, dynamic language - simply replaced in child objects. • Override a prototype method - analogous to class-based polymorphism • Replace an instance method - dynamic modification of objects • Extending a parent’s methods - ES5 syntax + “super”
  27. Overriding Methods function MyObj() {} MyObj.prototype.foo = () => 'bar';

    function YourObj() { this.foo = () => 'baz'; } YourObj.prototype = Object.create(MyObj.prototype); var obj = new YourObj(); obj.foo(); // 'baz';
  28. Replacing Methods function MyObj() { this.foo = () => 'bar';

    } var obj = new MyObj(); obj.foo = () => 'baz'; obj.foo(); // 'baz';
  29. Extending a Parent’s Methods function MyObj() { this.foo = 'foo';

    } MyObj.prototype.bar = function () { return this.foo; }; function YourObj() { this.baz = 'bar'; this.bar = function () { return MyObj.prototype.bar.call(this) + this.baz; }; } YourObj.prototype = Object.create(MyObj.prototype); var obj = new YourObj(); MyObj.call(obj); obj.bar(); // 'foobar';
  30. Extending a Parent’s Methods - super class MyObj { constructor()

    { this.foo = 'foo'; } bar() { return this.foo; } } class YourObj extends MyObj { constructor() { super(); this.baz = 'bar'; } bar() { return super.bar() + this.baz; } } var obj = new YourObj(); obj.bar(); // 'foobar';
  31. Polymorphism - Overloading Overloading is achieved with a single method

    signature since methods can accept a variable number of arguments, with no type-checking. var obj = { foo(arg1, arg2) { if (arguments.length === 2 && typeof arg1 === 'object') { // do behavior } else { // do other behavior } } };
  32. VS.

  33. Model Home vs. Blueprint1 A prototype is like a model

    home, you might keep it empty but you could live there. • A prototype is a working object, you can use it in your program • Metaphor breaks down when modifying a prototype A class is like a blueprint, it describes how a home is built but you can’t live there. • A class is a template for a working object, you can’t use it in your program 1. Metaphor borrowed from Reginald Braithwaite.
  34. Behavior Delegation vs. Inheritance In prototype-based languages, an object delegates

    behavior to another object • The only linkage between the objects is the delegation pointer • An object uses delegate behaviors without owning/referencing them In class-based languages, inheritance is achieved by extending existing classes • Child object must have a memory or structural similarity to its parent • Child object owns/references inherited behaviors
  35. Late vs. Early Binding Prototypal OO in JavaScript supports extreme

    late binding of behavior • Altering a prototype alters all existing instances created from it Most class-based languages enforce early binding of behavior • Once an instance is created, its behavior cannot be altered
  36. Summary JavaScript: • has minimalist objects, with multiple creation patterns

    • is a prototype-based, or prototypal, OO language • is not the only prototype-based language, but is by far the most mainstream • supports encapsulation, inheritance, and polymorphism • supports both prototypal and concatenative inheritance • differs considerably from class-based languages
  37. Resources JavaScript Classes - Reginald Braithwaite YDKS: this and Object

    Prototypes - Kyle Simpson Speaking JavaScript: Objects and Inheritance - Dr. Axel Rauschmayer Eloquent JavaScript: The Secret Life of Objects - Marijn Haverbeke