6. Every Object references a
Prototype
[[Prototype]]: Internal property pointing to
the object prototype.
Some implementations provide the non-
standard __proto__ as explicit reference.
7. // Constructor
function MyClass (msg) {
this.msg = msg;
};
// Instance method
MyClass.prototype.foo = function ()
{
console.log(this.msg);
};
var a = new MyClass(‘Hello!’);
a.foo(); // Hello!
MyClass.prototype
foo()
[[Prototype]
]
msg
a
[[Prototype]
]
[[Prototype]
]
Object.prototype
null
...
8. // Constructor
function ClassA () {
// call parent constructor
MyClass.apply(this, arguments);
};
// inherit from MyClass
ClassA.prototype = Object.create(MyClass.prototype);
// Instance method
ClassA.prototype.bar = function () {
console.log(this.msg + ‘ from bar’);
};
var obj = new ClassA(‘Hello!’);
obj.foo(); // Hello!
obj.bar(); // Hello! from bar
MyClass.prototype
foo()
ClassA.prototype
bar()
[[Prototype]]
[[Prototype]]
msg
obj
9. “Using inheritance as a vehicle to
reuse code is a bit like ordering a
happy meal because you want the
plastic toy”
Angus Croll.
10. Abstract* / Base* Classes
When inheriting from a Framework / Library
Class (e.g. Views, Components, Controllers) and
you find common methods or repeated code in
several subclasses, often a Base Class is
created to “share” that common code.
13. It’s OK for simple functions...
var max = Math.max.apply(null, array);
14. … but code becomes wordy
var instance = {
msg: ‘Hello from instance’
};
//borrowing foo method from MyClass
MyClass.prototype.foo.apply(instance); // Hello from instance
//borrowing bar method from ClassA
ClassA.prototype.bar.apply(instance); // Hello from instance from bar
//borrowing foo method from ClassA inherited from MyClass
ClassA.prototype.foo.apply(instance); // Hello from instance
16. What is a Mixin?
A Mixin is a class that is, often, not intended to
be instantiated, but is combined into another
class.
Usually it is merged into a Class.
In JavaScript, we can use Objects as Mixins.
17. Mixins: Benefits
Encourage code reuse.
Can be seen as a workaround for
Multiple Inheritance.
Avoid the inheritance ambiguity (The
diamond problem) linearly.
19. function MixedClass () {
// call mixin constructor
MyClass.apply(this, arguments);
};
// apply Mixin
Object.assign(MixedClass.prototype,
MyClass.prototype);
// Instance method
MixedClass.prototype.bar = function () {
console.log(this.msg + ‘ from bar’);
};
var obj = new MixedClass(‘Hello!’);
obj.foo(); // Hello!
obj.bar(); // Hello! from bar
MixedClass.prototype
foo()
[[Prototype]
]
msg
obj
[[Prototype]
]
[[Prototype]
]
Object.prototype
null
...
bar()
20. EventEmitter as a Mixin
function MyClass() {
// call Mixin constructor
EventEmitter.call(this, arguments);
}
Object.assign(MyClass.prototype, EventEmitter.prototype);
var obj = new MyClass();
obj.on(‘event’, function ( ) { console.log(‘event!’); });
obj.emit(‘event’);
24. The Diamond Problem cont’d
Object.assign(DerivedClass.prototype, ClassA.prototype, ClassB.prototype);
var d = new DerivedClass();
d.foo() // from ClassB
Object.assign(DerivedClass.prototype, ClassB.prototype, ClassA.prototype);
var d = new DerivedClass();
d.foo() // from ClassA
25. Calling an Overridden Method
….
Object.assign(DerivedClass.prototype, ClassA.prototype, ClassB.prototype);
DerivedClass.prototype.foo = function() {
// call “overridden” foo from A
ClassA.prototype.foo.apply(this, arguments);
}
26. Problems
Methods and properties are overridden based on
declaration position / implementation.
Refactoring (adding/renaming methods) can
cause “silent issues”.
Calling an overridden method is wordy and error
prone.
28. What is a Trait?
Composable Units of Behavior.
A special type of class with no state.
Can be seen as Incomplete classes.
Defines behavior and access state thru
required accessors.
30. Composing Behavior
May require a set of methods to serve as
parameters for the provided behavior.
(Incomplete Classes)
Can be composed from other traits.
Name collision is solved by the Developer
(aliases or exclusions)
31. Conflict Resolution
Conflict arises when we combine two or more
traits providing identically named methods that
do not originate from the same trait.
Alias: A conflicting method can be “renamed”.
Exclusion: We can solve the conflict by just
excluding the method explicitly.