Learning Duck Typing in Javascript | Hacker Noon


Mac Wasilewski Hacker Noon profile picture

During the day a developer. A husband and dad at night.

Recently I started thinking about OOP in Javascript. Having been heavily involved in functional React for the last 2.5 years it wasn't easy.

You know basic OOP concepts are: encapsulation, inheritance, abstraction, and polymorphism. I have been looking at a good example of polymorphism in Javascript.

In dynamic languages, it exists in the form of duck typing. Duck what?

If something quacks like a duck, it is a duck.

Polymorphism is when a different function gets called depending on the type of objects on which that function is executed. So is it a duck? Call the duck() function! Is it a dog? Call the dog() one!

I'm pretty sure that you use any of the above on a daily basis. Have you ever used Array.map, Array.filter. Sure you did! But to be able to call those methods and object must be:

"an iterable, an object must implement the @@iterator method, meaning that the object (or one of the objects up its prototype chain) must have a property with a @@iterator key which is available via constant Symbol.iterator."

Source: Mozilla

Translating the above duck typing explanation into this example if an object implements an iterable, it must be iterable! So call the iterator methods!

And bam! We proved that polymorphism exists in dynamic languages!

What about creating our own example?

function Cat (name) { this.name = name;
} Cat.prototype.sound = function() { console.log('Miau')
} function Dog (name) { this.name = name;
} Dog.prototype.sound = function() { console.log('Woof')
} function makeSound(soundMaker) { soundMaker.sound()
} const purr = new Cat('Purr');
const pluto = new Dog('Pluto'); makeSound(purr)
makeSound(pluto)

In the above, we have two different objects, but both implement a sound method and a makeSound function. And now we are back to our initial definition: Polymorphism is when a different function will get called depending on the type of objects on which that function is executed. So exactly what happens in our silly example above.

Looking for something more serious? Imagine you have several types of users, and each of them needs a location address generated based on the type. Perhaps the developers are in San Francisco, the lawyers in Boston, etc. So each object would implement an assignOfficeAddress method which would store a different address in the database.

Now on new user creation, you would just call for example a createUser function which would call assignOfficeAddress() without having to care which user you are creating.

How does it help? The code is clearer, there are fewer if, else, or switch statements but the most important of all - creating a new type of user is just creating a new object and implementing a new assignOfficeAddress method.

The createUser stays the same and you do not have to worry about updating the switch or if/else anymore, just call the createUser which will correctly call the correct method.

Lead Photo by Ravi Singh on Unsplash

Join Hacker Noon

Create your free account to unlock your custom reading experience.