Dependency Injection (js)

ref – https://stackoverflow.com/questions/20058391/javascript-dependency-injection

Problem

So we have a Printer class with a prototype function ‘print’. It prints something to console depending on a public property in the constructor.

It’s not flexible because it ONLY has this feature of printing. The functionality can’t be switched out.

In order to make it more flexible:

1) we use a driver property to take on new classes with different printing functionalities.
2) Then in our print function, we simply call the functionalities.

In this example, we can just add/remove functionalities in Driver. As long as the name driverPrint is being executed in Printer, then we’re good.

So our Printer class is now more modular, clean and easy to understand but there’s still some inflexibility yet again.

Any time you use new keyword you are actually hard-coding something

In this case you are constructing a driver inside your Printer which in real world is an example of a printer that comes with a built-in driver that can never change!

A better version is to inject a driver at the time we construct a printer meaning you can make any type of printer, color or black&white, because this time the driver is being made in isolation and outside the Printer class and then given (INJECTED!) into the Printer…

The problem presented here is that we are creating a new printer each time we need our printer to print with a different driver! That is because we are passing our driver of choice to the Printer class at the construction time.

or example if now I want to do a color print I need to do:

Provide Setter

Providing a setter function can dynamically let you switch out different Drivers, thus switching up on your functionalities.

Dependency Injection using Duck Typing

ref – https://stackoverflow.com/questions/12762550/example-of-javascript-duck-typing

Functions in JavaScript are versatile. They can be used as subroutines, methods, constructors, namespaces, modules, and much more.

The reason people advise against using prototype chain inheritance (by using instanceof) in JavaScript is because it hides the true power of JavaScript. Functions are just as expressive if not more expressive than objects. This has been proven by Alonzo Church who’s work, Lambda Calculus, is Turing Complete.

To answer your question directly I’ll use functions to create a Turtle, a Lion and a Dolphin. Then I’ll demonstrate how a turtle is an OceanAnimal and a LandAnimal, how a lion is only a LandAnimal, and how a dolphin is only an OceanAnimal. I’ll conclude by explaining what is duck typing.

First let’s create the constructor for an OceanAnimal:

Next we’ll create the constructor for a LandAnimal:

Next we’ll create the constructor for a LandAnimal:

What’s happening here?

Okay, we want Turtle to inherit from both OceanAnimal and LandAnimal. So we’re calling LandAnimal.call(this) and OceanAnimal.call(this).
In this way we’re using the OceanAnimal and LandAnimal constructors as mixins. Thus Turtle inherits from both OceanAnimal and LandAnimal without actually becoming of type OceanAnimal or LandAnimal.

Connecting through prototype chain can work but it will take more work via connecting their prototypes

Another thing to notice is that we’re setting the type property on the prototype of Turtle instead of inside it. This is because type is the same for all turtles. Thus it’s shared. The name of each turtle on the other hand may vary and hence it’s set inside the constructor.

Since Lion is a LandAnimal we only mix in the LandAnimal constructor.

Similarly for a Dolphin:

Now that we have created all the constructors let’s create a turtle, a lion and a dolphin:

Awww, now let’s set them free:

Okay, so what’s duck typing? We know that yoyo is an OceanAnimal and a LandAnimal. However if we do yoyo instanceof OceanAnimal or yoyo instanceof LandAnimal then it returns false. What?

You: Stupid JavaScript. A Turtle is an OceanAnimal and a LandAnimal!
JavaScript: Not from where I’m standing. All I know is that it’s a Turtle.
You: But if it swims then it’s an OceanAnimal, and if it walks then it’s a LandAnimal.
So since JavaScript is such a party pooper we’ll have to create our own test to check if an object is an OceanAnimal and if it’s a LandAnimal.

Let’s start with an OceanAnimal:

Similarly, for a LandAnimal:

So now we can use isOceanAnimal(yoyo) instead of yoyo instanceof OceanAnimal, and isLandAnimal(yoyo) instead of yoyo instanceof LandAnimal; and both these functions will return true for our beloved yoyo. Yay!