Inheritance Basics in JS
(or Borrowing a Stapler)
Hi! I’m Daoud, a JavaScript developer with a long history in education. I’ll try to explain some beginner-intermediate JS concepts with analogy, code examples and *zero* foo and bar (I promise!) Feel free to contact me if you have any questions about what I’ve written.
Prerequisites:
Just some ES6 syntax, like the spread operator and classes. It would help to understand ‘scope’, ‘context’ and
this
, but not essential for understanding this post and starting to use prototypes.
The Welcome
After some vigorous rounds of interviews, you made it! You’re the new employee of The Company and it’s time to receive your welcome pack. Things are a bit haphazard, no one seems to have officially on-boarded you, but a helpful colleague’s there to get your welcoming documents in order and hand you and a stapler (all for yourself!). Suddenly letting her smile drop, she looks you sternly in the eye and says:
“This stapler is for you. It’s only for you.”
Almost as quickly, things revert back to happy pleasantries, and a few moments later it’s time to find your desk. Understandably, stood holding a set of three loose A4 pages and a stapler, the first thing you do is staple them together.
Great! Your shiny new stapler works just as you’d expected.
A few hours after settling in at your computer, a shabby, unshaven guy introduces himself as ‘Jon’. You get the feeling he’s been here for a very long time. Jon seems to be holding a cluster of loose documents himself:
“Is that a stapler?”, he asks. “Back when I joined, they weren’t handing them out. Can I borrow it?”
You think back to that bizarre moment with the other colleague… “No, I’m afraid not”, you sheepishly reply. “This stapler’s mine, if you need one I’m afraid you need to see the same person I saw.”
Jon looks less than impressed; giving you one last look which seems to scream ‘you’re really going to make me walk down the corridor to get a stapler?’, he ambles towards your helpful colleague’s office.
Jon has his own
staple()
function now. Even though thestaple()
functions onnewEmployee
andjon
are identical, they exist twice in the computer’s memory.
The Cutback
“We spent how much on staplers?!” The Boss is standing over his desk looking at the latest report from the budget department, thinking about his 6-year-old daughter and her constant pestering for a swimming pool. He looks at his desk — and the unused Swingline stapler that’s sat there for years. “Why does everyone get their own stapler? They can all just ask to use mine.”
The Boss calls HR immediately: “From now on, I want to try giving new recruits their own documents, but stop giving them staplers! They can borrow my stapler if they ever need it.”
Your helpful colleague taps you on the shoulder. “I’m sorry, I just spoke to HR, you have to on-board officially through them. Something about new policy. Oh, and I need your stapler back.”
There is only one
staple()
now: it’s ontheBoss
. Remember,theBoss
is just a variable we’re using to refer toEmployee.prototype
; the function exists asEmployee.prototype.staple()
.A constructor call (
new Employee
) populates a new object through use of the wordthis
by calling the function from within it. In this way,this
is the person ‘being helped’, which is to say thatthis
isjon
whenjon.staple()
is called andnewEmployee
whennewEmployee.staple()
is called. For simplicity,this
is only for use when you’re going to be using prototypes, as code is going to live in functions ‘elsewhere’ up the prototypical chain and needs to have a word for referring to the place where it’s being called.Final word: arrow functions have no ‘context’, meaning that
this
will fall back to the context of the preceding scope. Sometimes this is extremely useful, but this is ‘Inheritance Basics’ so I won’t go too deep; just know thatthis
will only refer to the object where the function is called if it’s written in a good ol’function ()
.
You hand the stapler back to the boss with a polite but rather timid “thank you”. He beams; he can see little Abigail putting on her arm-bands in no time. ‘Yes, this is perfect’, he thinks. ‘Let’s make this official procedure’.
What follows is ‘syntactical sugar’, meaning a cleaner, easier way of writing exactly the same functionality. This bears repeating:
class
in JavaScript, unlike object-oriented languages, just calls a constructor function and puts methods on a shared prototype (like the above).
A middle-manager has spotted your fresh-faced enthusiasm and knows you’re the new recruit; she want you on their team. Rushing over to you, a rather over-enthusiastic lady shakes your hand and introduces herself with what seems a forced smile. “We need people like you over in Finance, I think you’ll find we’ve got a reputation for being the ‘fun-lovers’ of the company!” She’s still shaking your hand. Out of awkwardness you find yourself replying “sure, I’ll pop over”.
“Great! We’re constantly inviting members of our team to exclusive get-togethers and events. In fact, we’ve got one coming up!”
She hands you a brightly-coloured flyer decorated with tiki statues. “I know what you’re thinking,” she continues, “more paper. But remember, you still get all the general perks of being in the company. I hear the Boss has a beautiful stapler.”
Jon catches a glimpse of your invite. “Wait… did you join Finance? Are they celebrating anything? Can I come?”
jon.getInvite(); // 'jon.getInvite() is not a function'
Sorry Jon, you’re an
Employee
but not aTeamMember
. Jon gets help putting his documents away and access to thestapler()
, but that’s it! You are both descendants ofEmployee.prototype
but only you are also a descendant ofTeamMember.prototype
.
Jon wanders back to his desk with a sullen look. You wonder if your roommate has a shirt with palm trees you can borrow.
A Brief Note
‘…But why can’t I just give everyone a damn stapler?!’
Some people will decry OOP in JavaScript specifically because a class
is just a constructor function and some methods on its prototype (not the true ‘blueprint’ it can be in other languages), others because this
immediately means that context has to be maintained, others because functional programming and ‘mix-ins’ suit them better (when you’re ready, I have an article on that!). However, if you have 50 methods which need to be accessed on 1000 objects, the difference between 50 and 50,000 functions in memory may have a performance impact. Whatever the case, you will likely see prototype
and/or class
in the wild.
After all, you will have used some of them already…
const numArray = new Array(4, 2, 1, 3);
numArray.length; // 4
numArray.sort(); // [1, 2, 3, 4]
Now you know why MDN refers to it as ‘Array.prototype.sort()’!