5 Guys: The Evolution of Classes in JavaScript – part 5
Here’s our highly evolved Guy:
var Person = function (name, basics) { this.name = name; this.stuff = basics || {}; this.index = -1; }; Person.prototype.find = function (where, keep) { var label = where.split("."), box = this.stuff; while (label.length > 1) { if (typeof box[label[0]] === "undefined") { if (keep) { box[label[0]] = {}; } else { return; } } else { box = box[label.shift()]; } } return [box, label[0]]; }; Person.prototype.keep = function (what, where) { var found, box, label; if (where) { found = this.find(where, true); } else { found = [this.stuff, this.index += 1]; } box = found[0], label = found[1]; if (typeof box[label] === "undefined") { box[label] = what; } }; var Guy = function (name, basics) { var person = new Person(name, basics); this.have = function (what) { if (typeof person.find(what) !== "undefined") { return true; } else { return false; } }; this.show = function (what) { var found, box, label; if (typeof what === "undefined") { found = [person, "stuff"]; } else { found = person.find(what); } box = found[0]; label = found[1]; if (typeof box[label] === "object") { return JSON.stringify(box[label]); } else { return box[label]; } }; this.please = function (action) { var request = Array.prototype.slice.apply(arguments); request.shift(); if (typeof action === "function") { action.apply(person, request); } else { if (person[action]) { person[action].apply(person, request); } } }; }; Guy.prototype.keep = function (what, where) { this.please("keep", what, where); }; var bob = new Guy("Bob"); bob.keep({socks: 2}); bob.show("0");
During the refactoring of Person, it became obvious that the “keep” method was really a Person method that Guy implemented.

Now, we can safely introduce our Guy to another Guy and trust that their stuff will stay where we put it.
Proto-q

January 5th, 2011 at 6:53 am
I’ve posted a detailed response to this in my blog, with a number of critiques of this design, but the biggest one can be described by this code:
var george = new Guy(“George”);
george.keep({creditCards: ["Visa", "Amex"]}, “wallet”);
george.please(function() {pickpocket = this.stuff;});
console.log(pickpocket); // {“wallet”:{“creditCards”:["Visa","Amex"]}}
pickpocket.wallet.creditCards = [];
console.log(george.show(“wallet”)); // {“creditCards”:[]}
You can see the whole response at http://scott.sauyet.com/thoughts/archives/2011/01/04/no-classes-in-javascript/
January 5th, 2011 at 7:18 am
Thanks for comments.
I don’t think “please” is unsafe. It represents a way to prevent unintended side effects due to passing an object reference beyond the concerns of the function using it. It does not represent an inability to tamper with Guy’s stuff. But if you’re going to tamper with Guy’s stuff, you have only one method to do so and you must be explicit. That alone can save hours of troubleshooting.