DEV Community

Cover image for Duck Punching in JavaScript (with Example)
Ekansh Kothiyal
Ekansh Kothiyal

Posted on

Duck Punching in JavaScript (with Example)

We have the famous Duck Test:

If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck!

Coasting off that, we have Duck Punching (or Monkey Patching) in programming — a technique wherein alterations are made to a dynamic code during runtime without altering the source code.

Here is a great Consolia Comic strip to give you a better understanding in a funnier graphical way (if you’re into that):


Duck Punching - Consolia Comics

Source: Consolia-Comic

So let’s dive straight into an example and get our hands a little dirty:

Problem Statement

We have the popular indexOf function in JavaScript’s String prototype. The indexOf function returns the first occurrence of the search value inside the string that calls it.

'King, are you glad you are the king?'.indexOf(you);
// returns 10
Enter fullscreen mode Exit fullscreen mode

Suppose you wanted to do something extra on top of this function by extending the legacy indexOf function. You were asked to add an optional parameter that would give you the last occurrence index instead — a simple boolean flag.

Let’s do some duck punching -

There you go! But let’s break that down a little bit.

We start with the simple Duck Punching pattern:

const oldMethod = Class.prototype.method;
Class.prototype.method = function (arguments) {
// Do Your Magik Thang!
return oldMethod.call(this, arguments);
}
Enter fullscreen mode Exit fullscreen mode

Explanation: In the first line — we save the legacy prototype method inside a variable. In the subsequent lines, we redefine this method and do our ‘thang’ and we have extended the capabilities of a legacy function.

First, we initialize the old method to a new variable and then assign the indexOf method to a new method.

const legacyIndexOf = String.prototype.indexOf;
String.prototype.indexOf = function () {
}
Enter fullscreen mode Exit fullscreen mode

Second, we add a new parameter getLastIndexFlag that defaults to false and we have two conditions based on its value. If the getLastIndexFlag value passed is false/null, we use the existing indexOf() functionality in the if block. But if the getLastIndexFlag is set to true, we get into the else block where we reverse the string using the Array method and call our legacy indexOf().

String.prototype.indexOf = function (searchValue, fromIndex, getLastIndexFlag = false) {
if (!getLastIndexFlag) {   
        return legacyIndexOf.call(this, searchValue, fromIndex);  
    } else {   
        return legacyIndexOf.call(this.split(' ').reverse().join(' '), searchValue, fromIndex);  
    }
}
Enter fullscreen mode Exit fullscreen mode

Let’s try it out:

'King, are you glad you are the king?'.indexOf(you, null, true);
// returns 14
Enter fullscreen mode Exit fullscreen mode

Voila! There is your better version of indexOf as per your workplace needs!

Note: The 2nd parameter - null is passed for the fromIndex parameter that tells what index to start the search for in the original indexOf function.

So that was one example of Duck Punching. You can basically extend from the idea and work with your use case. A great way to articulate the advantage of this is how Paul Irish puts it -

a way to fulfill your own feature request on a library.

Future

Duck Punching has somewhat become less of a thing now by 2020 (or so I have been told by my more experienced colleagues). There are better methods using do the same thing (yet to explore). It still was a fun thing to read about and from my experience still a common coding tool in your back pocket.

Cheers!

Top comments (0)