Prototypes and Inheritance in JavaScript
WHO am i?
Chris Langton
- Community <3 Speaker for meetups
- Python <3 Django, Pandas, Hadoop
- PHP <3 PHP7 ZF2 CI Doctrine
- Raspberry Pi <3 My fish can sms me!
- Blogger with publications in WDW, Pi Weekly, Openshift
- chrislangton84@gmail.com
- github.com/chrisdlangton
- www.nodewiz.biz
- @chrisdlangton
The two pillars of JavaScript
JavaScript is pretty good at letting you code poorly.
But both pillars are equally important.
- Prototypal Inheritance (objects without classes, and prototype delegation, aka OLOO-Objects Linking to Other Objects)
- Functional Programming (enabled by lambdas with closure)
Prototypal Inheritance
- Classical and prototypal inheritance are fundamentally and semantically distinct.
- Instances inherit from other instances through concatenative inheritance
- Literally Objects Linking to Other Objects - OLOO
Don't be Shy
- You can and should ask questions
- The only dumb questions are ones you dont ask
Example
new func()
Produces a new object that inherits from
func.prototype
The `new` keyword is used to invoke a constructor.
What it actually does is:
- Create a new instance
- Bind `this` to the new instance
- Allows `instanceof` to check whether or not an object’s prototype reference is the same object referenced by the .prototype
- Names the object type after the constructor, which you’ll notice mostly in the debugging console. You’ll see `[Object Foo]`, for example, instead of `[Object object]`
In Practice
Add functionality through Prototypal Inheritance to your own Object definitions.
function newobject(o) {
function Func() {}
Func.prototype = o;
return new Func();
}
var yQuery = newobject(jQuery);
It takes an existing object as a parameter and returns an empty new object that inherits from the old one.
If we attempt to obtain a member from the new object, and it lacks that key, then the old object will supply the member.
Objects inherit from objects.
IRL
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
}
newObject = Object.create(oldObject);
These can then act as prototypes for even newer objects.
We don't need classes to make lots of similar objects.
native Objects
You can introduce new functionality to native Objects in the same manner as your own Object definitions.
Number.prototype.multiplyBy = function (number) {
return this * number;
}
Test
(123).multiplyBy(2)
> 246
What Will Go Wrong?
Everything
If debugging is the practice of removing bugs from software... then programming must be the practice of adding them.
You will have to make mistakes to learn how to fix them
Constructors
Classical OOPfunction Obj() {
/* do your constructor things here */
return this;
}
Obj.prototype.foo = function() {
return 'foo'
}
Obj.prototype.bar = function() {return 'bar'}
var obj = new
object();
obj.foo();
> foo
obj.bar();
> bar
Obj.foo()
> Uncaught TypeError: Obj.foo is not a function
If you’re creating constructor functions and inheriting from them, you haven’t learned JavaScript.
Namespace
Namespacing is a technique employed to avoid collisions with other objects or variables in the global namespace.
JavaScript doesn't have built-in support for namespaces like other languages, it does have objects and closures which can be used to achieve a similar effect.
Closure
A closure is a function which remembers it's environment in which it was created.
So, we'll use a self-executing anonymous function that exports an object definition to its namespace.
(function(){ // private area, away from the global scope
var privateProp = function(){
return this;
};
privateProp.prototype.get = function(key){
return this[key];
};
privateProp.prototype.set = function(key, value){
this[key] = value;
return this;
};
window.mynamespace = privateProp;
})();
Scope
For our previous 2 examples we have introduced a fatal flaw, and that is scope.
Though we have come today to learn about constructors, and namespaces, and closures, all in an attempt to manage scope.
These rely entirely on and can be identified by the `new` keyword.
All of these paradigms are classical inheritance NOT Prototypical Inheritance.
Avoid `new` - use .prototype
Explained
Using the definition from earlier
var obj = new mynamespace();
obj.set('foo','bar').get('foo');
> foo
Without `new`
obj = undefined ???
var obj = mynamespace();
obj.set('foo','bar').get('foo');
> Uncaught TypeError: obj.set is not a function
obj
> window
Where window came from
We attempted to simulate
namespace using a closure but in our simulated
constructor we referenced `this`, another flaw.
But we can handle that! Right?
(function(){
var privateProp = function() {
if (this === window)
return new privateProp(arguments);
return this;
};
window.mynamespace = privateProp;
})();
This is getting complicated, and we haven't even yet added functionality, and any additional methods are now constrained.
Want to repeat this for all objects?
DRY - use Prototypical Inheritance over Classical.
DRY - use Prototypical Inheritance over Classical.
Prototypes and Inheritance in JavaScript
By Chris Langton
Prototypes and Inheritance in JavaScript
- 591