Skip to content

Instantly share code, notes, and snippets.

@etsuo
Last active September 3, 2015 02:00
Show Gist options
  • Save etsuo/364813d8449fd7e6ebe1 to your computer and use it in GitHub Desktop.
Save etsuo/364813d8449fd7e6ebe1 to your computer and use it in GitHub Desktop.
Javascript Prototype Notes
(function() {
'use strict';
// essentially a parent "class" - these are not abstract entities
// per se that can be instantiated. However, when you call
// new Foo('some value'); then Foo is executed and what's returned
// is a new object with a copy of the values from Foo -- this
// points to the new copy of Foo...
function Foo(name) {
this.name = (name === undefined) ? 'Name was not set' : name;
}
// Associate a reference to a new function called myName() with Foo()
Foo.prototype.myName = function() {
return this.name;
};
// test the parent object
var a = new Foo('J.P.');
console.log('Foo');
console.log(a.myName());
/********************************************************************/
// essentially a child "class"
// note: Foo.call(this, name) - this causes Foo() to be executed in
// the context of Bar's this when new Bar(...) is called. Because
// Foo() is called in the context of Bar's this, Bar ends up with
// Foo's this.name.
function Bar(name, label) {
Foo.call(this, name);
this.label = label;
}
// dump Bar's default prototype chain and create a copy
// of Foo's to attach to bar - this is how Bar gets Foo's
// functions (myName()).
//
// Object.create means that Bar has Foo's prototype chain but not
// the other way around (see the link test below). You could use
// new Foo(), but that would cause a constructor call of Foo(),
// not something you want when you're simply wiring up the relationship
// off your objects.
Bar.prototype = Object.create ( Foo.prototype );
// Associate a reference to a new function called myLabel() with Bar()
Bar.prototype.myLabel = function() {
return this.label;
};
var b = new Bar('J.P.', 'Test Label');
// You now have an object b that is a Bar which
// has a copy of Foo's prototype chain that Bar then
// attached a reference to the function myLabel.
// Bar has the property name and label.
// test the child object
console.log('Bar');
console.log(b.name);
console.log(b.label);
console.log(b.myName());
console.log(b.myLabel());
// Note that Bar is linked to Foo in some mutatible ways
Foo.prototype.linkTest = function() {
console.log('Linked!');
};
b.linkTest();
// But not the other way around
var c = new Foo('test');
console.log((c.myLabel === undefined) ? 'not present' : 'weird, it was found');
// You can test if something is the prototype of something else like this:
console.log('Foo is prototype of c? ' + Foo.prototype.isPrototypeOf( c ));
console.log('Foo is prototype of b? ' + Foo.prototype.isPrototypeOf( b ));
console.log('Foo is prototype of a? ' + Foo.prototype.isPrototypeOf( a ));
console.log('Bar is prototype of a? ' + Bar.prototype.isPrototypeOf( a ));
// The object.create way of doing things:
var foo = {
name: '',
myName: function() {
console.log( "My name is " + this.name );
}
};
// This approach requires ES5
var bar = Object.create( foo, {
label: { value: '', writable: true},
myLabel: { value: function() {
console.log('My name is ' + this.name + ' and my label is ' + this.label);
}}
});
bar.name = "J.P.";
bar.label = "Test Label";
bar.myLabel();
// This approach can be polyfilled pre ES5
var bar2 = Object.create( foo );
bar2.name = 'J.P.';
bar2.label = 'Test Label';
bar2.myLabel = function() {
return 'My name is ' + this.name + ' and my label is ' + this.label;
};
console.log(bar2.myLabel());
var bar3 = Object.create( bar2 );
bar3.color = 'blue';
bar3.myLabel = function() {
return 'My name is ' + this.name + ' and my label is ' + this.label + ' and my color is ' + this.color;
};
console.log(bar3.myLabel());
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment