Skip to content

Modifying the JavaScript String Prototype

When manipulating strings in JavaScript, it is often necessary to perform certain functions to escape characters, decode them, and perform other string manipulations. JavaScript makes it easy to modify the String prototype, making it possible to create new methods on String types. As of late, I’ve preferred this method (pun intended) over creating custom functions.

I was recently working on a project in which I was using JavaScript to output HTML (my Google History download tool). I needed to escape special HTML characters in the string, in order to prevent problems with the output being mangled by any < followed by > characters in the strings I was outputting. I created a simple String method that emulates PHP’s htmlentities function:

String.prototype.htmlEntities = function() {
	return this.valueOf().replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}
foo = "<pre>This string has HTML tags</pre>";
bar = foo.htmlEntities(); // bar contains: &lt;pre&gt;This string has HTML tags&lt;/pre&gt;

It’s quite rudimentary, and simply chains together a few replace calls to search/replace &, <, >, and “ characters with the appropriate HTML escape characters. Unfortunately JavaScript provides no htmlentities equivalent, but it is easy enough to recreate via a simple String method.

If you are encoding strings to be used in URLs, you’ll want to use the escape(), encodeURI(), and encodeURIComponent() JavaScript functions. Each function varies slightly in the characters it converts. If you want, you can convert them into String methods rather than use them as functions:

String.prototype.escape = function() {return escape(this.valueOf());}
String.prototype.encodeURI = function() {return encodeURI(this.valueOf());}
String.prototype.encodeURIComponent = function() {return encodeURIComponent(this.valueOf());}

special_chars = '~!@#$%^&*(){}[]=:/,;?+\'"\\';
str1 = special_chars.escape(); // str1 contains: %7E%21@%23%24%25%5E%26*%28%29%7B%7D%5B%5D%3D%3A/%2C%3B%3F+%27%22%5C
str2 = special_chars.encodeURI(); // str2 contains: ~!@#$%25%5E&*()%7B%7D%5B%5D=:/,;?+'%22%5C
str3 = special_chars.encodeURIComponent(); // str3 contains: ~!%40%23%24%25%5E%26*()%7B%7D%5B%5D%3D%3A%2F%2C%3B%3F%2B'%22%5C

Writing methods for built-in JavaScript may be a bit of overkill, but it’s a nice way to demonstrate how easy it is to create new JavaScript methods for the String object. To learn more about these URL escaping functions, be sure to visit: http://xkr.us/articles/javascript/encode-compare/.

Perhaps a better example for another String manipulation method you may want, is a method to remove tags:

String.prototype.stripTags = function() {
	return this.valueOf().replace(/<[^>]+>/g, "");
}
foo = "<pre>This string has HTML tags<pre>";
bar = foo.stripTags(); // bar contains: This string has HTML tags

A couple of more tips when creating String methods in JavaScript:

  • When you’re writing new methods for strings, be sure to refer to this.valueOf() to obtain the value of the string object itself
  • If you create any variables within your new methods, be sure to use the var directive to declare/assign the variables. If you do not use the var directive, the internal variables will have a global scope, which can wreak havoc on your code!

The last tip really applies to any object methods and custom JavaScript functions you create. Although it can be convenient that JavaScript does not require explicit declaration of variables and types, it can be problematic to debug if you do not declare variables within object methods and global functions.

Any variables declared in an object method or function without the var directive will be global. If you reuse variable names in multiple methods/functions (such as “x” or “i” for loop variables, for example), you may experience very unexpected results if you do not explicitly declare them with the var directive.

1 thought on “Modifying the JavaScript String Prototype”

Leave a Reply

Your email address will not be published. Required fields are marked *