Duck Punching in JavaScript (with Example)
Tags: javascript, programming, duckpunching
Published: 2020-06-19 20:32:24

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](https://consolia-comic.com/) strip to give you a better understanding in a funnier graphical way (if you’re into that):

<figure>
<img src="https://static.consolia-comic.com/comics/ducks-1-duck-punching.png" alt="Duck Punching - Consolia Comics" style="width: 100%;" />
<figcaption>Source: <a href="https://consolia-comic.com/comics/ducks-1-duck-punching" target="_blank">Consolia-Comic</a></figcaption>
<figure>

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

### Problem Statement 
We have the popular [`indexOf` function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf) in JavaScript’s String prototype. The indexOf function returns the first occurrence of the search value inside the string that calls it.

```javascript
'King, are you glad you are the king?'.indexOf(‘you’);
// returns 10
```

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 -

{% gist https://gist.github.com/chunkybyte/73e51c319634c17119a1cbf44e192a15 %}

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

We start with the simple Duck Punching pattern:

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

**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.

```javascript
const legacyIndexOf = String.prototype.indexOf;
String.prototype.indexOf = function () {
}
```

**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()`.

```javascript
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);  
    }
}
```

Let’s try it out:

```javascript
'King, are you glad you are the king?'.indexOf(‘you’, null, true);
// returns 14
```

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](https://www.paulirish.com/2010/duck-punching-with-jquery/) 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!*