From fc3e135d7002bebaad7f8cf254d7836a90da0ca8 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Sun, 8 Dec 2013 05:30:24 +0400 Subject: [PATCH] Added a brief and simple JavaScript OOP rundown... Signed-off-by: Alex A. Naanou --- js-oop.js | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100755 js-oop.js diff --git a/js-oop.js b/js-oop.js new file mode 100755 index 0000000..c51b230 --- /dev/null +++ b/js-oop.js @@ -0,0 +1,130 @@ +/********************************************************************** +* +* The basics of JavaScript OOP +* +* +**********************************************************************/ +// +// The value of 'this' +// ------------------- +// + function f(){ + console.log(this) + this.a = 1 + } + var o = { f: f } + +// +// 'this' is always the "context" of the function call, in JS a context +// can be: +// - implicit +// - root context + f() // 'window' or 'module' is implied, this is + // equivalent to: window.f() +// - 'new' context + new f() // here a context will be created and passed to + // 'f's 'this', for more details on what 'new' + // does see the next section. +// - explicit: +// - the object on the left side of "." or the [ ] attribute access: + o.f() // o is the context + o['f']() // the same as the above +// - the object explicitly passed to .call(..) or .apply(..) methods +// as first argument: + f.call(o) // o is the context +// +// +// +// What's 'new'? +// ------------- +// + function O(){ + this.attr = 123 + } + var o = new O() + +// +// 'new' creates a new context object and passes it to the function +// being called (the constructor), this new object has several special +// attributes set: +// o.constructor -- references the object (constructor) used to +// construct the object o (instance) +// o.__proto__ -- references the constructor prototype, same as: + o.constructor.prototype === o.__proto__ +// this is used to identify the object via: + o instanceof O +// +// The 'new' expression returns the context object after it has been +// populated by the constructor function. +// +// NOTE: when using 'new', the function return value is ignored. +// +// +// The values set on 'this' by the constructor are instance attributes, +// i.e. they are stored in the specific instance being created. +// +// NOTE: calling the constructor is not required, but not calling it +// will not run the initialization code that would otherwise +// populate the object. i.e. no instance values will be created. +// +// +// The instance has another type of attribute accessible through it that +// is not stored in it, but rather in it's prototype (o.__proto__), or +// rather the constructor's prototype (o.constructor.prototype). For +// more details see the next section. +// +// +// +// The object's 'prototype' +// ------------------------ +// + function f(){} + console.log(f.prototype) // f {} + +// +// The unique prototype object is created on every function definition. +// The prototype is instance-like of the function to which it is assigned. +// +// NOTE: since the prototype has .__proto__ set to Object, technically +// it's not a strict instance of the type it defines, so: + f.prototype instanceof f +// will return false. +// +// Each unresolved attribute access on the "instance" will resolve to its +// prototype (o.__proto__ or o.constructor.prototype). +// + O.prototype.x = 321 + console.log(o.x) // 321 + +// +// Since the prototype is a JS object that adheres to the same rules as +// any other object, if the attr is not resolved in it directly it will +// be searched in its prototype, and so on. +// This principle enables us to implement inheritance. +// + var OO = function(){ + // call the base constructor... + O.call(this) + } + // chain the two prototypes... + OO.prototype = new O() + // this is to make things coherent for oo below... + OO.prototype.constructor = OO + + var oo = new OO() + + console.log(oo.x) // 321 + console.log(oo.constructor.name) // 'OO' + +// +// So in the example above local attributes (in 'oo') will be searched +// first, then oo.__proto__ (instance of O), then in O.prototype, and +// then in Object.prototype. +// +// oo -> oo.__proto__ -> (oo.__proto__).__proto__ -> ... +// +// +// +// +/********************************************************************** +* vim:set ts=4 sw=4 : */