7 days of WordPress plugins, themes & templates - for free!* Unlimited asset downloads! Start 7-Day Free Trial

Next lesson playing in 5 seconds

  • Overview
  • Transcript

4.1 Parasitic Inheritance

Parasitic inheritance isn't inheritance at all; it's object modification. But regardless, it has its uses and you'll learn how to apply it in this lesson.

4.1 Parasitic Inheritance

Inheritance is one of the key traits of object-oriented programming. It is how we reuse existing code so that we end up writing less code overall. And JavaScript is an object-oriented programming language, so you would be correct to think that it has inheritance. Now, there's really only one true way of inheriting one object from another in JavaScript, and that's to use what's called prototypal inheritance. And we will look at that in the next lesson. But in this lesson we're going to focus on something called parasitic inheritance, which really isn't inheritance at all. It's just augmenting an existing object with more specialized functionality. And you typically see parasitic inheritance used with just plain objects that come out of a factory function. If you are defining a data type of your own, you're better off using prototypal inheritance. So everything that we do in this lesson is going to be with objects created with our factory function. So we have this createPerson function to createPerson objects. But let's say that we are now working on a system where we need to manage employees. Now, an employee is just a more specialized person. So let's start by creating the factory function to create an employee. So we need the first name, we need the last name, and we also need the position of this employee, so manager, salesman, you know, things like that. Now, we can get a lot of our stuff done by simply just copying and pasting the code that we have inside of the person factory function. Because after all, for firstName lastName, we are simply going to be returning those values. And as far as greet is concerned, we want this existing functionality but we want to augment it a little bit. Now, we can take this approach, but the whole idea behind inheritance is to reuse existing functionality so that we don't have to copy and paste or do a lot of rewriting of code. You essentially have to rewrite a few things, but you end up rewriting less. So the first thing you need with a parasitic inheritance is the object that you are going to augment. So we need our person object. So we will create our person object. We'll pass in firstName and lastName and that will give us the base functionality that we want. Now, we need a position property for our new employee. So we can use the defineProperty method. So we can pass in person as the object. And the name of the property is simply going to be position. And then we need our descriptor. It's going to have a getter which is simply going to return the position value. And so we have that position. Now, as far as the greet method is concerned, this is a little bit more involved, because we can't just say person.greet equals and then a new function, because that's going to overwrite the existing greet method. Now, we could just copy and paste, but once again, we want to reuse existing functionality. And all we really want to do here is to say, hello, name, and then my name is, you know, the first name, but then we want to tack on the position of that person. So if somebody is a manager and their name is John Doe, they'll say, hello person, my name is John Manager. So instead of rewriting all of that code, the first thing we can do is get a reference to the existing greet method. So let's just call that personGreet. And we will say person.greet. That will give us the function object so that we can then use that inside of the new greet method. Now, we do need to accept a name so that we can then pass that to the person.greet function. That will give us the base functionality. But then we also want to concatenate the person's position. So in this case, we will concatenate this.position. And then finally we want to return our person object. So we retrieve our base object. We then augment that object with new functionality. And then we return that object. And that is the essence of parasitic inheritance. Well, let's see this in action. Let's go to the index html file and let's create a couple of employees. The first will be called John, and so we will call createEmployee. The first name will be John, and let's make the last name Doe. And John Doe is going to be the manager. And then we will need somebody that is not a manager. So we can create Jim Smith. So we will call this Jim. We will call createEmployee once again. First name is Jim. Last name is Smith. And Jim is going to be a salesman. Now, we are going to walk into a store, and then both John and Jim are going to rush to us and they are going to greet us. So let's alert John and greet. And let's say that they are greeting a customer named Jane. So we will take that and then make John greet Jane as well. Let's run this in the browser. And we should see the first message, Hello, Jane, My name is John Manager. And then the second, Hello, Jane, My name is Jim Salesman. So we were able to take the base functionality of a person object and then augment it so that it could represent an individual employee. And it was relatively easy to do. Well, let's add some complexity. Let's go back to the createPerson function. And then let's add another property to our person objects. We'll call it fullName. And it will return the first and last names concatenated together. Now, we're going to do this with the definePproperty method. We are going to make this as part of the object definition. So our object is person, the name is fullname, and then for our descriptor we are going to have a getter, which is going to simply return this.firstName and then concatenate that with this.lastName. So we are using the first and lastName properties as opposed to the values that were passed to the function. And then we want to use this fullName property inside of the greet method, so that we are no longer just saying, my name is and then the first name, but we are telling whoever it is that we are greeting what the fullName is. So we will change that. Now, in the employee object, we want the fullName to still say the first name and last name, but we also want to add in the position of that employee. So we are essentially going to negate the whole reason as to why we overrode the greet method. So let's just comment that out, just so that we still have it. But instead of overriding the greet method, we want to override the fullname property. Now, the easiest way to do that is to simply just copy and paste from createPerson into createEmployee. And then we could concatenate the position. However, that also defeats the purpose of inheritance. And, unfortunately, we just can't say return this.fullName and then concatenate in the position, because that is going to give us a circular reference. Because fullName, in this case, is going to refer to this property that we are defining here. So this isn't an option. However, we can kinda do the same thing that we did with the greet method, because all the get accessor is is a function. And we can get that function by getting the descriptor for the firstName property. So let's create a variable called fullNameDescriptor. And we want to use a method on object called getOwnPropertyDescriptor. You pass in the object that contains the property that you want to get the descriptor of and then the name of the property. And this is going to give you the object that has the get accessor, the set accessor, and all of the other options that you have specified whenever you define a property. So it's basically going to give us this object right there. So we have that descriptor. Now we just need the function that is assigned to the get accessor. So we can say fullNameGet, and that is going to be equal to fullNameDescriptor.get that gives us that function that we can then use inside of this new fullName method. So instead of this.fullName, we will simply call fullNameGet and there we go. Now, this is actually going to give us an error, because whenever you define a property, the property is not configurable. That means that we can't really do anything to that property. We can't redefine it or anything like that. And if we look at the developer tools, we will see that that is the error that we get. So let's refresh with the tools. Now, one of the things about Edge is that we cannot dock the developer tools. And I have no idea why they released it without that functionality. But I'm just going to dock the developer tools on the right and have the browser on the left, so that we can see both things. Now, you can see that the error says, cannot redefine non-configurable property, fullName. And that's because whenever we defined the fullName property on the person object, we didn't specify it as being configurable, because by default they are not. If you define a property with the defineProperty method or the defineProperties method, then those properties are not configurable. However, we can easily change that by setting the configurable option to true, and this is done inside of the property descriptor. So that's something else that you would add to that descriptor object. So now that we have set fullName to be configurable, we won't run into that error anymore. But we are still going to run into an issue. Let's go back to the browser. And whenever we refresh, we see, Hello, Jane, My name is undefined undefined and Manager. So we're almost there. It's just that we aren't getting the firstName and the lastName properties. And the reason being because whenever we get the get accessor, which is a function, that function isn't bound to this person object and we want to bind it to the person object. So we can use the bind method. We'll pass in the person that will create a new function object that is bound to the person object that will then allow us to use fullNameGet inside of our fullName property. And now we will see the first name and the last name in our message. So, once again, we have Hello, Jane, My name is John Doe, Manager, and then Hello, Jane, My name is Jim Smith, Salesman. So parasitic inheritance is relatively straightforward. We take an existing object and then we augment it with specialized functionality. But how we go about augmenting that object just really depends upon what it is that we want to augment. Sometimes it's just really easy to do, and then other times there are a few hoops that we have to jump through. Now, in the next lesson, we are going to look at prototypal inheritance, which is true inheritance in JavaScript.

Back to the top