2

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?

2
  • 3
    You don't. The prototype of a type is global (or, at least as global as the type itself). Commented Sep 9, 2014 at 15:41
  • 1
    there is no such thing as "private" in javascript. Commented Sep 9, 2014 at 15:41

2 Answers 2

4

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);
}
Sign up to request clarification or add additional context in comments.

Comments

2

This is not possible due to String is a global object. It doesn't matter where you change it or its prototype, it will be affected everywhere.

In your case you should declare a helper function within your class.

function Template() {

    function stringReplaceAll(str, search, replace) {}

}

This one will only be available in your class.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.