A more prototype based JavaScript

JavaScript, like io, is a Prototype-based language. Prototype-based programming is a variation of OO, one of the main differences being the absence of classes. Objects are not instantiated, but are instead cloned, with additional behavior defined on the clones of the Prototypes.

Io provides a clone method, with the option to specify the cloned object’s state and behavior within a do construct:

Person := Object clone do(
  givenName := "Kirk"
  surname := "Hammett"
)

JavaScript allows functions to be used in conjunction with the new keyword, thus acting as Constructors.

person = function(givenName, surname) {
  this.givenName = givenName
  this.surname = surname
}

kirk = new person('Kirk', 'Hammett')

The use of new presents a, perhaps, odd choice for a language without classes that need to be instantiated from their static definitions. It would be interesting to have the option to code a cloned Object’s state, behavior and composition within the scope of its cloning.

For example, let’s extend JavaScript’s base Object by giving it a clone function:

Object.prototype.clone = function() {
  var target = {}
  for (var i in this) {
    if (target == this[i]) {continue}
    if (typeof this[i] == 'object') {target[i] = this[i].clone()}
    else if (this[i] != undefined) {target[i] = this[i]}
  }
  if (arguments[0]) {arguments[0](target)}
  return target
}

The clone function effectively copies all of the Prototype’s attributes, functions, etc to the cloned object. In addition, it passes a reference of the target as an argument to a delegate function which can be provided as an argument to clone. This can be used to configure the cloned object within the scope of the clone function:

Guitarist = Object.clone(function(g) {
  g.shred = function() {alert('shred!')}
})

kirkHammett = Guitarist.clone(function(kirk) {
  kirk.guitar = 'ESP'
  kirk.plays = function() {alert(kirk.guitar)}
})

kirkHammett.shred()
kirkHammett.plays()

What about composition? Objects in io can attach unlimited protos to their slots. Similarly, JavaScript objects are open to modification and extension at runtime, although I am not aware of a standard way to achieve mixin functionality in core JavaScript - jQuery and the Prototype Framework both offer extend functions.

For the above example, we could have something like:

Object.prototype.mixin = function(other) {
  for (var i in other) {
    if (this == other[i]) {continue}
    if (typeof other[i] == 'object') {this[i] = other[i].clone()}
    else if (other[i] != undefined) {this[i] = other[i]}
  }
}

With the mixin function, objects can be extended through composition:

Repeater = Object.clone(function(r) {
  r.times = function(i, delegate) {
    for (var j=0; j < i; j++) {delegate(j)}
  }
})

Guitarist = Object.clone(function(g) {
  g.shred = function() {alert('shred!')}
})

kirk = Guitarist.clone(function(k) {
  k.mixin(Repeater)

  k.shredThreeTimes = function() {
    k.times(3, function() {k.shred()})
  }
})

kirk.shredThreeTimes()

I find experimenting with this approach in JavaScript possibly offers a more structured, concise development canvas.

2 Responses to “A more prototype based JavaScript”

  1. napyfab:blog&#187; Blog Archive &#187; links for 2007-10-25 Says:

    [...] Nutrun » Blog Archive » A more prototype based JavaScript (tags: javascript object io programming language example) [...]

  2. Michael Christenson II Says:

    This is actually a really good approach. I especially like the mixin idea. Something to try when I ahve time … thanks :)

Leave a Reply