Pseudo Classical Style vs Objects Linking to Other Objects, in their own voices.
PCS: Thanks for having me, User.
OLOO: Pleasure to be here.
Moderator: Let’s get right to it. We asked both participants to supply an example of how their Object Creation pattern looks in code. Let’s begin with yours, PCS.
PCS: With pleasure!
Moderator: Could you run us through what exactly is going on here?
PCS: Of course. To begin, we declare a function that contains all the properties we’d like each new object created based on our function to contain. As you can see, each new Bike object will have their own tires and horn property. Next, if we wish to add functionality to our Bike objects, we need to define the Bike.prototype object.
Moderator: Ah yes, that makes sense. So the prototype of Bike is Bike.prototype. Simple!
PCS: Err…well, no. The prototype of Bike is actually Function.
Moderator: ….I’m sorry?
PCS: It’s very simple actually. Every function has a prototype object that contains, among other things, a constructor that points back to the function itself. What we are doing to add functionality to our Bike objects is to define that prototype object ourselves, and adding a method called go() as seen in the code above.
Moderator: So Bike.prototype is NOT the prototype of Bike?
PCS: Exactly. …hey, why are you laughing?
OLOO: Hahaha…I’m sorry…but this is just ludicrous. I mean, you’re saying that the function has a prototype, and a .prototype, and that those are different, and for some reason we have to remember all that.
Moderator: Please, wait your turn OLOO.
PCS: It’s not that difficult to remember! You just have to remember that functions have a prototype object, as well as having a prototype of their own (that in the above example is Function.)
Moderator: Lets move on. Tell us about the objects we can create with the Pseudo-Classical style.
PCS: Sure! Every object made in the Pseudo-Classical style will have their own copies of each property in the Bike function. Moreover, every object will also have their prototype set to the prototype object of Bike. So if we have a new object called ‘myNewBike’, we can see:
myNewBike.__proto__ === Bike.prototype //or
Object.getPrototypeOf(myNewBike) === Bike.prototype
Moderator: I see. So the prototype of myNewBike is the prototype of Bike.
PCS: Yes! Er, no. The prototype of myNewBike is the Bike.prototype object. Remember, the prototype of Bike is Function.
Moderator: Ah, yes, I forgot again. So, this myNewBike object has it’s prototype set to the Bike.prototype object when you make the variable declaration:
var myNewBike = Bike()?
PCS: Well…that will actually not do what you’re expecting. We need the keyword ‘new’.
OLOO: Yeah, ‘new’! More random things to remember! Isn’t it grand?
Moderator: OLOO please, you’ll have your chance to speak!
PCS: Again, it’s not that hard. To create a new object in the Pseudo-Classical style, you just need:
var myNewBike = new Bike();
Moderator: Got it. Looks pretty easy. But…at what point in your Bike function are the prototypes set? And what exactly is being returned here? It’s…not very clear…
OLOO: It’s not clear at all!
PCS: Ah, well, there are some things that go on behind the scenes when you invoke a function with the new keyword. When invoked with new, our Bike function above looks something more like this:
Moderator: So invoking a function with the new keyword will cause the function to return a new object whose prototype is set to the prototype object of the invoked function. Wow, that’s a mouthful.
OLOO: Make him tell you about the constructors next!
Moderator: Ah, yes, I noticed in your original Bike.prototype object definition, you add the property .constructor and assign it….’Bike’?
PCS: Yes. Every function has a prototype object, and every prototype object has a constructor property that points back to the function itself. That is, of course, unless you define your own prototype object for a function.
OLOO: Which is like one of the main reasons to do pseudo-classical object creation! Creating your own prototype objects with shared behavior, right?
PCS: Well, that is true. So you’ll have to remember to define the constructor property in the prototype object to be the function itself. This way, each object created with the prototype object will have a constructor property that points back to the original function. So, our myNewBike object will have a .constructor property that points to Bike, since it’s inheriting the prototype object of Bike upon it’s creation!
Modertor: That’s..umm…kinda confusing.
PCS: Let me rephrase. Each function has a prototype object. Prototype objects have a property called constructor that points back to the function. When an object is made with a function using the new keyword, that object inherits the prototype object of the function, and that prototype object still has a constructor that points to the original function that was called with new. So, we can access the constructor through each created object!
Moderator: That’s clearer I suppose…
OLOO: Glad we got that all straightened out, cause constructors are used all the time! Oh wait, no they’re not!
PCS: Hey! Just because a constructor only has use in maybe…the most rarest of situations, doesn’t mean it’s not useful!
Moderator: Ok, I think we have a handle on how things work in Psuedo-Classical object creation. Objects Linking to Other Objects, let’s move on to you. Do you have a code example to share?
OLOO: Indeed I do, and it’s way easier to understand than PCS!
Moderator: That’s it? Just one object?
OLOO: That’s the beauty of it! In OLOO, we only need one object. No splitting up everything into functions and prototype objects and constructors; everything we need is right there. Our Car object IS our prototype object!
Moderator: Can you run us through your code?
OLOO: Sure. When a new object is created using the OLOO pattern, each new object will have as it’s prototype the original object it was created with. So, if I have a variable called ‘myNewCar’, it’s prototype will be ‘Car’. Can’t get any easier than that!
Moderator: How exactly do you make a new Car object though? Something like:
var myNewCar = Car()?
OLOO: No, that would lead to problems with variable mutation. If we did something to the myNewCar variable that was mutating, our Car variable would also be effected and if we created more objects from Car, those later variables would be effected. Instead, we have an easy solution. We use:
var myNewCar = Object.create(Car).
Moderator: So what happens when we run that Object method? And what exactly is returned?
OLOO: Yes, empty. But thanks to prototypal inheritance and behavior delegation, we can still access the noise and info properties, as well as all the methods defined in the Car object.
Moderator: That seems…very straight forward actually…
PCS: Yeah but you can’t initialize anything at the point of creation! In PCS, since you’re using a function to create objects, you can send arguments to that function to initialize properties. For example:
OLOO: That’s true, which is why you define an initialization method in the object itself! Just call the initialization method after the object has been created with the arguments you’d like to include, like the init() method I’ve included above. For example:
var myNewCar = Object.create(Car).init(‘zooooom!’);
You just have to remember to also include a ‘return this’ statement in your initialization, otherwise ‘myNewCar’ is just going to be undefined.
PCS: Seems like a giant pain, having to create a whole initialization method when you can just include arguments when creating in object using PCS!
Moderator: Please PCS, we’re running low on time and need to keep moving. OLOO, could you elaborate more on prototypes? What exactly is the prototype of Car?
OLOO: The prototype of Car? Or the prototype object of Car?
Moderator: Both, please.
OLOO: Well, Car is an object, not a function. So, there is no prototype object for Car, and it’s own prototype is Object. It’s all very simple. Car is an object. It’s prototype is Object. It has no prototype object, because it’s not a function. If we look at objects created with Object.create(Car), we must remember that Car is the Prototype object for the newly created objects. In code:
myNewCar.__proto__ === Car //or
Object.getPrototypeOf(myNewCar) === Car
And since I know you’ll ask, the constructor for myNewCar is just Object, since myNewCar was created with the Object.create() method!
PCS: See, the constructor gets lost! In PCS, the constructor for a created object refers to the original Function that was used. In OLOO, the constructor is always Object!
OLOO: So? I’d wager that the vast majority of programmers can’t point to a single time they used a constructor in any useful way!
Moderator: PCS, OLOO, please. We’re running out of time. Any final remarks?
PCS: OLOO may be the latest style of doing things, but programmers have been using PCS for years. It’s tried and true, and if the rest of the code base is written in this style, you should use it too.
OLOO: Just cause it’s old, doesn’t mean it’s good. OLOO is clearer and cuts out the middle man of creating prototype objects and setting constructors. If the rest of the code base is written in OLOO style, you should follow suit and join the 21st century!
Moderator: That concludes our discussion for today, and I’d like to thank both participants for their time. I think our listeners, now more properly informed about the differences between each style, can choose the one suits their code best.