Replacing `String.prototype.valueOf` in JavaScript

I am creating a DSL that will benefit from being able to crack some of the internal elements of JS. I understand that this is a very bad idea in general use of JS, but for my purposes it is good. The following code works fine:

var str = new String("blah"); str.valueOf = function() { return 10 } console.log(str * 10); // outputs 100 

But this is not so:

 var str = "blah"; str.valueOf = function() { return 10 } console.log(str * 10); // outputs NaN (because str === "blah") 

Can someone who understands the insides explain a little what is happening here? What is the difference between these two examples?

And now, if I want to change the String prototype itself, so I can set the valueOf method of all strings, regardless of when / where / how they are created? Is it possible? Unfortunately this does not work:

 String.prototype.valueOf = function() { return 10 } console.log("blah" * 10); // NaN 

Although it does:

 String.prototype.valueOf = function() { return 10 } console.log("blah".valueOf() * 10); // 100 

So:

 String.prototype.valueOf = function() { return 10 } console.log(new String("blah") * 10); // 100 

Why does the JS engine handle "blah" and new String("blah") differently? Thanks!

By the way, here is a good article that led me to study this material.

+5
source share
1 answer

When you do

 var str = "blah"; 

you create a string primitive but when you do

 var str = new String("blah"); 

you call the constructor and create a String object .

When you have an object, javascript internally calls valueOf when trying to use this object into which the primitive should be inserted.

For primitives, the opposite is that in order to be able to bind methods, javascript needs an object, and internal primitives are wrapped with a new String when calling the methods of the object on the primitive.

In other words, when you have a string primitive and you try to call str.valueOf , javascript will internally execute new String(str) before it calls valueOf and returns a value.
However, when you try to use a string directly, you still have a primitive, and valueOf not called, the antiderivative value is inserted directly.

From MDN

Note that JavaScript distinguishes between String objects and primitive string values. (The same goes for Boolean and Numbers .)

String literals (indicated by double or single quotes) and strings returned from String calls in the context of a non-constructor (i.e. without using the new keyword) are primitive strings.

JavaScript automatically converts primitives to String objects so that you can use the String methods of the object for primitive strings.

In contexts where a method should be called in a primitive string or property search, JavaScript will automatically wrap the string primitive and call the method or perform a property search.

+5
source

Source: https://habr.com/ru/post/1262616/


All Articles