Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why toString is not a generic function in javascript

I was trying to do something like this.

 var myFunc = function() {}
 myFunc.prototype = new String();
 myFunc.prototype.replace = function() {return 'hii, Mr '+ this.toString();}       

 var oVal = new myFunc('Jyotirmay');
 oVal.replace();

o/p :: Uncaught TypeError: String.prototype.toString is not generic(…)

Why "function not generic" error comes actually in general?

As to be more clear, How can i pass my argument i.e Jyotirmay from inherited class to base class i.e string. So that i can get that value by calling any proper string function.

I don't want to get my passed value from my function by handling that variable in it. I want that to be handled by parent class. You can say super() in other languages.

like image 944
Jyotirmay Avatar asked Nov 01 '22 01:11

Jyotirmay


1 Answers

It is unclear what exactly you are trying to achieve from your question and comments, but perhaps this is all you are trying to do?

function myFunc(inputArg) {
    this.inputArg = inputArg;
}

myFunc.prototype = {
    replace: function () {
        return 'hii, Mr ' + this.inputArg;
    },
    
    toString: function () {
        return '' + this.inputArg;
    }
};

myFunc.prototype.valueOf = myFunc.prototype.toString;

function log(inputArg) {
    document.getElementById('out').appendChild(document.createTextNode(inputArg + '\n'));
}

var oVal = new myFunc('Jyotirmay');

log(oVal);
log(oVal.replace());
<pre id="out"></pre>

As to Why is toString not generic, this is because not all objects can be represented as a string by the same conversion method.

Update based on your latest comment

Native objects are notoriously difficult, if not impossible, to subclass in Javascript. There are a few hacks that will allow you partial success, but I would not recommend them and good luck across different environments.

Two (but not the only) such hacks are:

Stealing from an iframe

function stealObject(objectName, myVariableName) {
    var iframe = document.createElement('iframe');

    iframe.style.display = 'none';
    iframe.src = 'javascript:parent.' + myVariableName + ' = ' + objectName;
    document.body.appendChild(iframe);
    document.body.removeChild(iframe);

    return window[myVariableName];
}

function log(inputArg) {
    document.getElementById('out').appendChild(document.createTextNode(inputArg + '\n'));
}

try {
    stealObject('String', 'MyString');
    MyString.prototype.replace = function () {
        return 'hii, Mr ' + this;
    };


    var oVal = new MyString('Jyotirmay');

    log(oVal);
    log(oVal.toUpperCase());
    log(oVal.replace());
} catch (e) {
    log(e);
}
<pre id="out"></pre>

Doesn't work in SO snippets because SecurityError: Sandbox access violation: but can see it on this jsFiddle. typeof oVal will return object and not string and oVal instanceof String will be false. oVal.constructor === String will return false.

Another hack

function MyString() {
    this.str = '' + arguments[0];
};

with(MyString.prototype = new String()) {
    toString = valueOf = function () {
        return this.str;
    };
}

MyString.prototype.replace = function () {
    return 'hii, Mr ' + this;
};

function log(inputArg) {
    document.getElementById('out').appendChild(document.createTextNode(inputArg + '\n'));
}

var oVal = new MyString('Jyotirmay');

log(oVal);
log(oVal.toUpperCase());
log(oVal.replace());
<pre id="out"></pre>

The magic length property is broken in this one and you would need to call oVal.toString().length instead. typeof oVal will return object and not string but oVal instanceof String will be true. oVal.constructor === String will return true.

like image 60
Xotic750 Avatar answered Nov 15 '22 05:11

Xotic750