We have been debating how best to handle objects in our JS app, studying Stoyan Stefanov’s book, reading endless SO posts on ‘new’, ‘this’, ‘prototype’, closures etc. (The fact that there are so many, and they have so many competing theories, suggests there is no completely obvious answer).
So let’s assume the we don’t care about private data. We are content to trust users and developers not to mess around in objects outside the ways we define.
Given this, what (other than it seeming to defy decades of OO style and history) would be wrong with this technique?
// namespace to isolate all PERSON's logic
var PERSON = {};
// return an object which should only ever contain data.
// The Catch: it's 100% public
PERSON.constructor = function (name) {
return {
name: name
}
}
// methods that operate on a Person
// the thing we're operating on gets passed in
PERSON.sayHello = function (person) {
alert (person.name);
}
var p = PERSON.constructor ("Fred");
var q = PERSON.constructor ("Me");
// normally this coded like 'p.sayHello()'
PERSON.sayHello(p);
PERSON.sayHello(q);
Obviously:
- There would be nothing to stop someone from mutating ‘p’ in unholy
ways, or simply the logic of PERSON ending up spread all over the place. (That is true with the canonical ‘new’ technique as well). - It would be a minor hassle to pass ‘p’ in to every function that you
wanted to use it. - This is a weird approach.
But are those good enough reasons to dismiss it? On the positive side:
- It is efficient, as (arguably) opposed to closures with repetitive function declaration.
- It seems very simple and understandable, as opposed to fiddling with
‘this’ everywhere.
The key point is the foregoing of privacy. I know I will get slammed for this, but, looking for any feedback. Cheers.
There’s nothing inherently wrong with it. But it does forgo many advantages inherent in using Javascript’s prototype system.
instanceofwill not help you to identify its origin. You’ll be stuck using only duck typing.p.sayHello()can do different things forPERSONorANIMALdepending on the type Javascript knows about. This is a form of polymorphism. Your approach requires you to name (and possibly make a mistake about) the type each time you call a method.constructorfunction, since functions are already objects. YourPERSONvariable may as well be the constructor function.What you’ve done here is create a module pattern (like a namespace).
Here is another pattern that keeps what you have but supplies the above advantages: