Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@kkas
Last active March 22, 2017 13:38
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kkas/e9321e7dbb8e205e05d3 to your computer and use it in GitHub Desktop.
Save kkas/e9321e7dbb8e205e05d3 to your computer and use it in GitHub Desktop.
Object-Oriented JavaScript

Object-Oriented JavaScript

Scopes

Lexical Scope

  • the word describes the regions in your source code where you can refer to a variable by name without getting access errors.
  • Global scope:
    • if no functions are defined, every variable will be in this scope. **Every time you declare a function definition, a new lexical scope is created. **
    • it does not matter which file the source code are written in: they all share global scope.

Execution Contexts

When a program runs, it builds up storage system for holding the variables and their values. These in-memory scope structures are called Execution Contexts.

Closure

A closure is just any function that somehow remains available after those outer scopes have returned.

'this' keyword

  • There are 2 major differences between a regular parameter and the parameter 'this'.

    1. you don't get to pick the name for the parameter 'this'. It is always just going to be referred to as 'this'.
    2. you go about binding values to the parameter 'this' a bit differently from how you bind values to other parameters. There are 5 different ways to do that.
  • 'this' is an identifier to get the value bound to it, and gets bound to the correct object automatically.

  • What 'this' refers to is:

    • When you notice a dot to the left of a function invocation, meaning it was looked up as a property of an object, you can look to the left of that dot and see what object it was looked up upon. The object that a function is looked up upon when it's being invoked, that object is what the keyword, 'this', will be bound to. it has everything to do with that call time dot and the object that we find to te left of it.
    • Exception:
      • you can specify the value that you'd like the parameter 'this' to get bound to by using '.call()'
      • with 'new' keyword, 'this' refers to the brand new object being created in the fucntion (constructor).
var fn = function(one, two){
  log(this, one, two); // 'this' refers to global
}

var fn2 = function(one, two){
  log(this, one, two); // 'this' refers to obj, 'r'!!
}

var r = {}, g = {}, b = {};
fn(g, b);
fn2.call(r,g,b);
(Be careful when you pass a function as a parameter of another function)
setTimeout(r.method, 1000); // r will not be passed. 'this' still refers to the global object.

(you must do this...)
setTimeout(function(){
   r.method(g,b);
   }, 1000);  // now 'this' refers to 'r'.

Prototype Chains

Prototype chanis are a mechanism for making objects that resemble other objects.

In JavaScript, it provides the option of prototype chain to create two objects that have all the same property, instead of coping every property over from one object to another.

As a result of this feature, one object can behave as if it has all the properties of the other object, by delegating the failed lookups from the first object to the second one.

One-time Copy

var gold = {a:1};
console.log(gold.a); // 1
console.log(gold.z); // undefined

var blue = extend({}, gold); // Copy all the properites in gold to blue
blue.b = 2;
console.log(blue.a); // 1
console.log(blue.b); // 2
console.log(blue.z); // undefined

Prototype Delegation

  • ongoing lookup-time delegation
Object.create(objet_for_fallback);
(Example:)

var gold = {a:1};
var rose = Object.create(gold);
rose.b = 2;
console.log(rose.a); // returns 1, instead of undefined!!!
console.log(rose.b); // 2 (no delegation)
console.log(rose.z); // undefined. neither rose or gold has the property 'z'

gold.z = 3;
console.log(blue.z); // undefined
console.log(rose.z); // 3 (delegation)

object prototype

  • a top-level object that every JavaScript object eventually delegates to and where all the basic methods are provided for all objects

Object Decorator Pattern

  • There is a trade-off for the simplicity. the functions inside are created in each object.
  • You would use the decorator pattern to add some functionality to an object that already had some functionality in it at that point. In our example, we passed an empty object.
var carlike = function(obj, loc){
  obj.loc = loc;
  obj.move = function(){ // gets created for each object. trade-off.
    obj.loc++;
  };
  return obj;
};

var amy = carlike({}, 1);
move(amy);
var ben = carlike({}, 9);
move(ben);

Functional Classes

  • Simplest possible implementation of a class, which is a powerful form of functions that can be used to manufacture fleets of similar objects.

  • Decorator vs Class

    • Same, except that class generates the object (called, "instance") where as decorator acepts the modifing object as its argument)

Functional Shared Pattern

  • Functional class pattern with shared methods.
var Car = function(loc){
  var obj = {loc: loc};
  extend(obj, Car.methods);
  return obj;
};

Car.methods = {
  move : function(){
    this.loc++;
  },
  on : function() { /*...*/ },
  off : function() { /*...*/ }
};

var amy = Car(1); // Instantiating an object.
amy.move();
var ben = Car(9);
ben.move(); // 'this' in move() will refer to ben here.

Prototypal Classes

  • JavaScript does add something like the 'methods' automatically, 'prototype'.
  • The object is automatically created by the language. Nothing special about it: it's just an empty object.
  • Therefore, it doesn't delegate. You need to use Object.create() still if you need to delegate.
  • Prototype has a contructor, which points to the created function.
var Car = function(loc){
  var obj = Object.create(Car.prototype); // Object.prototype. nothing special but an object.
  return obj;
};

Car.prototype.move = function(){
  this.loc++;
};

var amy = Car(1); // Instantiating an object.
amy.move();
var ben = Car(9);
ben.move(); // 'this' in move() will refer to ben here.

console.log(Car.prototype.constructor);  // Car
console.log(amy.constructor);  // Car. amy doesn't have constructor property. Therefore, it delegates the failed lookup for a .constructor property to Car.prototype, which does has that property.
  • ambiguity

    • If someone says, "object1's prototype is object2.", a reasonable interpretation would be to think that field lookups on this first object should fall through to the second one. So, you might say "Amy's .prototype is Car.prototype" but this is not the relationship that Car has with Car.prototype.
    • In that case, car is a function object and field lookups on it will fall through to some function prototype, where all function objects delegate their field lookups.
    • The car function's relationship with Car.prototype is very different from the one that Amy has with Car.prototype.
    • This other relationship reflects the second interpretation of the statement, "object1's prototype is object2.". The relationship is that when a car function runs, it will create objects that delegate their field lookups to Car.prototype.
    • So, in this sense, you might say, Car's prototype is Car.prototype. So to review, saying Amy's prototype is Car.prototype means something very different from saying Car's prototype is Car.prototype.
  • "instanceof" checks to see if the right operand's .prototype object can be found anywhere in the left operand's prototype chain.

var Car = function(loc) {
  var obj = Object.create(Car.prototype);
  obj.loc = loc;
  return obj;
};
Car.prototype.move = function(){
  this.loc++;
};

var amy = Car(1);
amy.move();

console.log(Car.prototype.constructor);
console.log(amy.constructor);
console.log(amy instanceof Car); // true


var Dog = function() {
  return {legs: 4, bark:alert};
};

var fido = Dog();
console.log(fido instanceof Dog); // false

Pseudoclassical Patterns

  • Using "new" keyword infront of function objects, the function works in Constractor Mode. It adds the following, unvisible special 2 lines in the function call.
var Car = function(loc) {
 //this = Object.create(Car.prototype); // invisible but assumed.
 this.loc = loc;
 //return this; // invisible but assumed.
};

Car.prototype.move = function() {
  this.loc++;
}

var amy = new Car(1); // "new" keyword is the key.
  • This is just a syntactic convenience over top of the prototypal pattern.
  • The primary difference between prototypal patterns and Pseudoclassical Patterns is:
    • the number of performance optimizations that the JavaScript engines have implemented, that only apply when you are using Pseudoclassical Patterns!! means Faster!!

Superclasses and Subclasses

  • This is easy since we just use functional pattern.
// Superclass
var Car = function(loc){
  var obj = {loc: loc};
  obj.move = function(){
    obj.loc++;
  };
  return obj;
};

// Subclass
var Van = function(loc){
  var obj = Car(loc);
  obj.grab = function() { /*...*/ };
  return obj;
};

// Subclass
var Cop = function(loc){
  var obj = Car(loc);
  obj.call = function() { /*...*/ };
  return obj;
};

var amy = Car(1);
amy.move();
var ben = Car(9);
ben.move();
var cal = Car(2);
cal.move();
cal.call();

Pseudoclassical Pattern

// Superclass
var Car = function(loc){
  this.loc = loc;
};
Car.prototype.move = function() {
  this.loc++;
};

// Subclass
var Van = function(loc){
  //this = Object.create(Van.prototype);
  Car.call(this, loc);
};
Van.prototype = Object.create(Car.prototype);
Van.prototype.grab = function() { /*..*/ };
Van.prototype.constructor = Van;

var zed = new Car(3);
zed.move();

var amy = new Van(9);
amy.move();
amy.grab();

Very Nice Note about this course

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment