-
-
Save gryzzly/3902289 to your computer and use it in GitHub Desktop.
How JavaScript OOP works
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// constructor definition | |
var Foo = function() { | |
// when invoked with `new` it's as if the following implicitly happens | |
// this = { constructor: Foo }; | |
// return this; | |
}; | |
// For every function, `prototype` property is created automatically: | |
Foo.hasOwnProperty('prototype') // true | |
// This `prototype property` is an object, that holds any methods | |
// and properties which will be accessible to any objects created | |
// when the original [constructor] function will be invoked with | |
// `new` operator. We can modify it to extend functionality of future | |
// instances | |
Foo.prototype.log = function (message) { console.log(message); }; | |
// create new instance with 'new' | |
var x = new Foo(); | |
x.log('whoa') // logs 'whoa' to console | |
// create new instance without 'new' | |
// Above is almost equivalent to | |
var y = {}; | |
// illustration purposes only. __proto__ should not be accessed directly | |
y.__proto__ = Foo.prototype; | |
y.constructor = Foo; | |
// So now: | |
x.constructor === y.constructor // true | |
x instanceof Foo // true | |
y instanceof Foo // true | |
// How does inheritance work | |
var Bar = function () { | |
// inherit instance properties | |
// `call(context)` invokes a function with context of `this` | |
// set to given parameter object | |
Foo.call(this); | |
}; | |
// Set up prototype chain | |
// | |
// What we need to do is to have Foo.prototype object | |
// referenced as `__proto__` property of Bar.prototype | |
// | |
// This is how property look up works in JavaScript: | |
// you are accessing a property "baz" on object "fee" (`fee.baz`). | |
// | |
// JavaScript engine is looking for a property to be available directly | |
// on the object `fee`. If it doen't find such property, it goes up the | |
// prototype chain, by following the reference set as `__proto__` property | |
// of object `fee`. | |
// | |
// Best example will be any kind of object. Let's say we use object | |
// literal to create new object: | |
// | |
// var obj = {}; | |
// // immediately we will have all `Object.prototype` methods available | |
// obj.hasOwnProperty === Object.prototype.hasOwnProperty // true | |
// // this means internal `__proto__` property is automatically | |
// // set to point at `Object.prototype` | |
// // And same goes for arrays: | |
// var data = []; | |
// // they have access to all `Array.prototype` properties | |
// data.push === Array.prototype.push // true | |
// // but also to all `Object.prototype` properties | |
// data.hasOwnProperty === Object.prototype.hasOwnProperty // true | |
// | |
// Note: if new prototype or object itself creates a property with the same name | |
// as one already defined somewhere in prototype chain, it is called "to shadow" | |
// previously defined property. The original property may be still accessed by directly | |
// referring to a method, supplying it with the right context to be executed upon: | |
// | |
// `Array.prototype.push.call(this)` | |
// | |
// Let's look at the mechanics that will allow us to setup inheritance | |
// with JavaScript custom types | |
// | |
var ProtoCarrier = function () {}; | |
ProtoCarrier.prototype = Foo.prototype; | |
Bar.prototype = new ProtoCarrier; | |
Bar.prototype.constructor = Bar; | |
// is equivalent to | |
Bar.prototype = Object.create(Foo.prototype); | |
Bar.prototype.constructor = Bar; | |
// and also equivalent to | |
Bar.prototype.__proto__ = Foo.prototype; | |
// The final result will be that | |
(new Bar()) instanceof Foo // true | |
Foo.prototype.isPrototypeOf(new Bar()) // true | |
// And all methods and properties defined on `Foo.prototype` will | |
// be accessible for instances of `Bar` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment