Say I define a class Template()
within which I need to extend String
with some prototype
to add functionalities to it:
function Template() {
String.prototype.replaceAll = function(find, replace) {
return this.replace(new RegExp(find.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"), 'g'), replace);
}
this.test = function (){
return "hello".replaceAll("h", "y");
}
}
Now if I declare a new Template()
, the String.prototype
is public:
var myTemplate = new Template();
console.log(myTemplate.test()); // outputs "yello", this is desired
console.log("hello".replaceAll("h", "y")); // outputs "yello", this should not work
Whereas what I would want is for String
to go unchanged outside of the Template()
class while still being extended from within.
How do you declare a private prototype from within a class in javascript?
In general, you do the opposite; you create a new function, whose prototype is the "class" you want to extend, then you add the new methods to that function;
function MyString() {
}
MyString.prototype = new String();
MyString.prototype.replaceAll = function (find, replace) {
return this.replace(new RegExp(find.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"), 'g'), replace);
};
... you can create MyString
in whatever scope, so that it is as private or public as you want. Then, inside your scope you create instances of MyString
rather than String
. This gives you the extra ("private") prototypes you want.
However, string is a primitive, and primitives don't work like normal objects; specifically, they are autoboxed/ upcast to objects when you call methods on them. This will mean the above is not usable in your situation; as "abc".replaceAll()
will always autobox to a String
, not MyString
; and you can't tell JavaScript to do otherwise.
Instead, what you should be doing (since you shouldn't modify what you don't own anyway), is creating a helper function which you pass the string into to do your dirty work;
function replaceAll(str, find, replace) {
return str.replace(new RegExp(find.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"), 'g'), replace);
}