By Ran Bar-Zik | 3/27/2020 | General |Beginners

Monkey Patching in JavaScript

Monkey Patching in JavaScript

In this article, we’ll take a look at a technique called “monkey patching.” It’s a popular name for a basic technique in Javascript, but one that can be dangerous to use. However, at the right place and time, it can be quite useful and regardless, it’s at least something you should be familiar with. 

 

Programmers will often search for a property in a language, framework, or library, and end up disappointed to discover that it doesn’t exist. There are plenty of cases like this. For instance, you might discover that an array doesn’t have the method endsWith. Something along these lines:

const myArray = ['avi', 'itzik', 'yaki'];

console.log(myArray.endsWith('yaki')); // true

console.log(myArray.endsWith('sarah')); // false

If you run this code, you’ll get an error message:

Uncaught TypeError: myArray.endsWith is not a function

The simple reason for this is that the endsWith method exists in JavaScript only as the primitive data type of a text string and not in an array. But what if I somehow still want it in an array? A responsible programmer will create some kind of utils library along these lines:

 

const Utils = {
  endsWith: (arr, arg) => arr[arr.length - 1] === arg ? true : false,
}

const myArray = ['avi', 'itzik', 'yaki'];

console.log(Utils.endsWith(myArray, 'yaki')); // true;

But this approach is likely to be problematic. You need to remember that we have a Utils now and anyone who writes a bit more complex code knows that these reference libraries tend to swell up. In the end, it can be the best approach, but there is another way called “monkey patching.” This is when we change the code at runtime, or in JavaScript, change the object’s prototype in real-time. 

 

In JavaScript, we have prototypes, which constitute the base of the language. For every single object, we can access and change its method using prototype. This means I can give the primitive data type “array” the method endsWith so it's available in my arrays. Check it out:

Array.prototype.endsWith = function(arg) {
  return this[this.length - 1] === arg ? true : false;
}

const myArray = ['avi', 'itzik', 'yaki'];

console.log(myArray.endsWith('yaki')); // true

console.log(myArray.endsWith('sarah')); // false

 

From the time I added the property endsWith to Array.prototype, that property will be available to any array in my code, including external code.

 

I can, of course, also change an existing property. Not only in prototype but also in the global scope (once we had to use ‘window’ but today it’s ‘globalThis’). For instance, if I want every console.log to be printed as console.error, I can do something like this:

globalThis.console.log = (arg) => globalThis.console.error(arg);

So what’s so dangerous about this, and why do we need to be careful? I think it should be pretty obvious. Adding some property to a variable is probably OK, but if we change an existing property, it’s liable to break things in libraries and other uses in the code. It’s also likely to create uncontrollable dependencies. For example, if somewhere deep in my code I’m depending on having Array.endsWith, I’m likely to forget it depends upon code that ran earlier, and this will create unwanted complications in my code. 

 

If I need these kinds of additions, I can use decorators, which we’ll hopefully get into in a future article.

 

On the other hand, there is a responsible use of monkey patching. One is if we want to write errors or alerts in the console, and make them available only to programmers who are debugging the environment. Another is if we want polyfills to support old browsers, monkey patching is the only way to do it.

 

So if you still want to use monkey patching in your code, despite the warning, it’s best to wrap the usage in an additional method in the test where it exists. Personally? Other than debugging and in the console, I wouldn’t use it. But, it’s important to know about it and how it works.

About the author: Ran Bar-Zik is an experienced web developer whose personal blog, Internet Israel, features articles and guides on Node.js, MongoDB, Git, SASS, jQuery, HTML 5, MySQL, and more. Translation of the original article by Aaron Raizen.

By Ran Bar-Zik | 3/27/2020 | General

{{CommentsModel.TotalCount}} Comments

Your Comment

{{CommentsModel.Message}}

Recent Stories

Top DiscoverSDK Experts

User photo
3355
Ashton Torrence
Web and Windows developer
GUI | Web and 11 more
View Profile
User photo
3220
Mendy Bennett
Experienced with Ad network & Ad servers.
Mobile | Ad Networks and 1 more
View Profile
User photo
3060
Karen Fitzgerald
7 years in Cross-Platform development.
Mobile | Cross Platform Frameworks
View Profile
Show All
X

Compare Products

Select up to three two products to compare by clicking on the compare icon () of each product.

{{compareToolModel.Error}}

Now comparing:

{{product.ProductName | createSubstring:25}} X
Compare Now