Sid Ngeth's Blog A blog about anything (but mostly development)

Prototypes in Javascript

What is a prototype?

An object that exists on every function in javascript.

A function’s prototype: A function’s prototype is the object instance that will become the prototype for all objects created using this function as a constructor

An object’s prototype: An object’s prototype is the object instance from which the object is inherited.

var myFunc = function() {}
console.log(myFunc.prototype) // empty protototype object

var cat = {name: 'Fluffy'}
console.log(cat.__proto__); // note objects don't have a prototype but have a __proto__ object

function Cat(name, color) {
  this.name = name
  this.color = color
}

var fluffy = new Cat('Fluffy', 'White')

Cat.prototype.age = 3

console.log(Cat.prototype) // has a property age: 3
console.log(fluffy.__proto__) // has a property age: 3
console.log(Cat.prototype === fluffy.__proto__) // true - same prototype instance

var muffin = new Cat('Muffin', 'Brown')
console.log(muffin.__proto__) // has a property age: 3


fluffy.age = 4

//instance properties override prototype properties
console.log(fluffy.age) // 4
console.log(fluffy.__proto__.age) // 3

delete fluffy.age
console.log(fluffy.age) // 3 - looks up prototype chain

//Changing a Function's prototype
Cat.prototype = {age: 5}

var snowbell = new Cat('Snowbell', 'White')

console.log(fluffy.age) // 3 still refers to original prototype instance
console.log(muffin.age) // 3 still refers to original prototype instance
console.log(snowbell.age) // 5 gains new defined prototype
console.log(snowbell.age) // 5 gains new defined prototype

//Prototype chains
console.log(fluffy.__proto__) // Cat { age: 4 }
console.log(fluffy.__proto__.__proto__) // Object {}
console.log(fluffy.__proto__.__proto__.__proto__) // null

Prototypical inheritance

function Animal(voice) {
  this.voice = voice || 'grunt'
}

Animal.prototype.speak = function() {
  console.log('Grunt')
}

function Cat(name, color) {
  //call parent constructor for parent related initialization
  Animal.call(this, 'Meow')
  this.name = name
  this.color = color
}

Cat.prototype = Object.create(Animal.prototype) // Link the prototypes
Cat.prototype.constructor = Cat // Necessary to correct prototype chain references

var fluffy = new Cat('Fluffy', 'White')

fluffy.speak() // 'Grunt'

Inheritance using new ES6 class syntax

We have some syntatic sugar that makes it cleaner to set up inheritance

class Animal {
  constructor(voice) {
    this.voice = voice || 'grunt'
  }

  speak() {
    console.log(this.voice)
  }
}

class Cat extends Animal {
  constructor(name, color) {
    super('Meow')
    this.name = name
    this.color = color
  }
}

var fluffy = new Cat('Fluffy', 'White')
fluffy.speak() // "Meow"

An important note is that the constructor object is a class not a constructor function on the object.

Also, members of classes are not enumerable by default. E.g., the speak function will not show up on the Object.keys or loop over the properties of the Animal class.

Closures in Javascript

What is a closure?

A closure is when a function “remembers” its lexical scope even when the function is executed outside that lexical scope.

function makeAdder(x) {
  return function(y) {
    return x + y;
  };
}

var add5 = makeAdder(5);
var add10 = makeAdder(10);

console.log(add5(2));  // 7
console.log(add10(2)); // 12

add5 and add10 have both become closures because they share the same function body definition but store different environments and close over the x and y independently. The key mechanism at work here is the inner function is be transported out and returned.

Module pattern

A useful application of closures is the module pattern which can provide a means of encapsulation.

var foo = (function() {
  var o = { bar: "bar" };

  return {
    bar: function() {
      console.log(o.bar);
    }
  };
})();

foo.bar(); // "bar"
foo.o // "undefined" - akin to a private member

this keyword in Javascript

The following notes are a resummarization from Kyle Simpson as a note to myself

What is this? Every function, while executing, has a reference to its current execution context

What determines which object a functions this points to? What’s the default?

  • Default and Implicit Binding rule
function foo() {
  console.log(this.bar);
}

var bar = "bar1";
var o2 = { bar: "bar2", foo: foo };
var o3 = { bar: "bar3", foo: foo };

//the call below is a normal call and uses default binding
//in strict mode this will be undefined
//in non strict mode it wil be the global
foo();    //"bar1"

//below we illustrate implicit binding
//we make a reference to o2 as the owner or containing object
//and use it to call the function, 'this' now points to o2's 'this' context
o2.foo(); //"bar2"
o3.foo(); //"bar3"
  • Using the new keyword
function foo() {
  this.baz = "baz";
  console.log(this.bar + " " + baz);
}

var baz = "bar";

// below we will get a brand new object with a new 'this' context
// also the object inherits from foo's prototype
// if there is no return statement, 'this' will be implicitly returned
var baz = new foo();

//the above will log "undefined bar"
//this is because this.bar is set on our new this context
  • Explicit Binding with a call, apply or bind(as of ES5)
function foo(a,b) {
  console.log(a + " " + b + " " + this.bar);
}

var bar = "bar1";
var obj = { bar: "bar2" };

foo(); // "bar1" due to default binding

//first argument is the owner object or 'this' context
foo.call(obj, "a", "b"); // "a b bar2" - explicitly use obj as this
foo.apply(obj, ["a", "b"]); // "a b bar2" - same except extra arguments in array
foo = foo.bind(obj, "a", "b");
foo(); // "a b bar2"  - note we have to explicitly call foo after binding

Double Dispatch

How can you code a computation that has many cases, the cross product of two families of classes? In a language like Ruby that does not support method overloading, we would need to rely on a low level pattern known as double dispatch.

The example below illustrates the dependency on the class of the object(Doctor or Dentist) and the class of the input object(Adult or Child). If we don’t use double dispatch we get a nasty case of if or switch statements

#Not using double dispatch
class Doctor
  def work_on(patient)
    if patient.is_a? Child
      #patient.do_child_work
    elsif patient.is_a? Adult
      #patient.do_adult_work
      #elseif potential maintenance explosions here
    end
  end
end

class Dentist
  def work_on(patient)
    if patient.is_a? Child
      #patient.do_child_work
    elsif patient.is_a? Adult
      #patient.do_adult_work
      #elseif potential maintenance explosions here
    end
  end
end

Using double dispatch below, we can cleanly decouple the type of work to be done and get rid of type checking

#Using double dispatch
class Doctor
  def work_on(patient)
    patient.dispatch_work(self)
  end

  def work_on_adult(patient)
    do_checkup(patient)
  end

  def work_on_child(patient)
    assure_presence_of(patient.guardian)
    ask_questions_to(patient.guardian)
    do_checkup(patient)
    give_cheap_toy_to(patient)
  end

  private
  def do_checkup(patient)
    puts "Checking all your adult aparts"
  end
end

class Dentist
  def work_on(patient)
    patient.dispatch_work(self)
  end

  def work_on_adult(patient)
    drill_as_hard_as_you_can(patient)
  end

  def work_on_child(patient)
    use_bubble_gum_toothpaste(patient)
    give_toothbrush_to(patient)
  end

  private
  def drill_as_hard_as_you_can(patient)
    puts "Drilling very hard! on #{patient}"
  end

  def use_bubble_gum_toothpaste(patient)
    puts "Heard you like bubble gum?"
  end

  def give_toothbrush_to(patient)
    puts "Here's a free toothbrush!"
  end
end

class Adult
  def dispatch_work(doctor)
    puts "dispatch_work called on an adult"
    doctor.work_on_adult(self)
  end
end

class Child
  def dispatch_work(doctor)
    puts "dispatch_work called on an child"
    doctor.work_on_child(self)
  end
end

p1 = Adult.new
c1 = Child.new

d1 = Dentist.new
d1.work_on p1
d1.work_on c1

d2 = Doctor.new
d2.work_on p1

Addendum (3/7/2024): Understanding Double Dispatch

In software development, particularly in object-oriented programming, handling complex interactions between different types of objects can be challenging. One such scenario arises when we need to perform computations that involve multiple combinations of object types. In languages like Ruby, which lack native support for method overloading, we often rely on patterns like double dispatch to address these challenges.

Understanding Double Dispatch:

Double dispatch is a design pattern that allows us to dynamically dispatch method calls based on the types of two objects involved in a computation. It involves a two-step process:

  1. First Dispatch: The method call is dispatched based on the type of the first object.
  2. Second Dispatch: Within the method called in the first dispatch, another method call is dispatched based on the type of the second object.

This approach effectively decouples the logic for handling different combinations of object types, leading to cleaner and more maintainable code.

Possible Alternative:

Alternatively, we could refactor the code to use duck typing and interface extraction. This approach involves defining a Patient interface with a do_work method, which both Adult and Child classes implement. The Doctor and Dentist classes then directly call the do_work method on patient objects, eliminating the need for double dispatch.

# Define an interface for patients
module Patient
  def do_work(doctor)
    raise NotImplementedError, "This method must be implemented by subclasses"
  end
end

# Define classes for Adult and Child patients implementing the Patient interface
class Adult
  include Patient

  def do_work(doctor)
    doctor.work_on_adult(self)
  end
end

class Child
  include Patient

  def do_work(doctor)
    doctor.work_on_child(self)
  end
end

# Define classes for Doctor and Dentist
class Doctor
  def work_on_adult(adult)
    puts "Checking all your adult parts"
  end

  def work_on_child(child)
    assure_presence_of(child.guardian)
    ask_questions_to(child.guardian)
    puts "Checking all your child parts"
    give_cheap_toy_to(child)
  end

  private

  def assure_presence_of(guardian)
    # Logic to assure the presence of a guardian
  end

  def ask_questions_to(guardian)
    # Logic to ask questions to the guardian
  end

  def give_cheap_toy_to(child)
    puts "Here's a free toy for you!"
  end
end

class Dentist
  def work_on_adult(adult)
    puts "Drilling very hard!"
  end

  def work_on_child(child)
    puts "Using bubble gum toothpaste"
    puts "Here's a free toothbrush for you!"
  end
end

# Usage
p1 = Adult.new
c1 = Child.new

d1 = Dentist.new
d1.work_on p1
d1.work_on c1

d2 = Doctor.new
d2.work_on p1

This refactoring promotes a more flexible and maintainable design, aligning with the Interface Segregation Principle (ISP) of the SOLID principles.

In summary, double dispatch is a powerful design pattern for handling complex interactions between objects in object-oriented systems. By leveraging double dispatch effectively, developers can write cleaner, more maintainable code that is better suited to handle the intricacies of real-world applications.

Javascript click vs touch events

If your application needs to respond to both mobile touches and desktop clicks you could write the following

function bind_button(selector, subselector) {
  $(selector).on('click', subselector, function(event) {
    handleEvent();
    return false;
  });

  if('touchstart' in window) {
    $(selector).on('touchstart', subselector, function(event) {
      handleEvent();
      return false;
    });
  }
}