Duck Punching in JavaScript

Duck Punching in JavaScript

Subscribe to my newsletter and never miss my upcoming articles

Duck Punching in JavaScript (with Example)

Image for post

Photo by Aleks Marinkovic on Unsplash

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):

Comic explaining the concept of Duck Punching

Image Source: consolia-comic.com

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

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 -

Duck Punching Example in JavaScript — Extending indexOf function capabilities.

Simple JavaScript Example of 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);
}

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 () {
}

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

Let’s try it out:

'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 null parameter 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. We have legit APIs to work with inside many libraries which might be a better way to work. Though it was still a fun thing to read about and still a common coding tool in your back pocket.

Cheers!

 
Share this