valueOf() vs. toString() in Javascript
The reason why ("x="+x) gives "x=value" and not "x=tostring" is the following. When evaluating "+", javascript first collects primitive values of the operands, and then decides if addition or concatenation should be applied, based on the type of each primitive.
So, this is how you think it works
a + b:
pa = ToPrimitive(a)
if(pa is string)
return concat(pa, ToString(b))
else
return add(pa, ToNumber(b))
and this is what actually happens
a + b:
pa = ToPrimitive(a)
pb = ToPrimitive(b)*
if(pa is string || pb is string)
return concat(ToString(pa), ToString(pb))
else
return add(ToNumber(pa), ToNumber(pb))
That is, toString is applied to the result of valueOf, not to your original object.
For further reference, check out section 11.6.1 The Addition operator ( + ) in the ECMAScript Language Specification.
*When called in string context, ToPrimitive does invoke toString, but this is not the case here, because '+' doesn't enforce any type context.
String.valueOf() vs. Object.toString()
According to the Java documentation, String.valueOf()
returns:
if the argument is
null
, then a string equal to"null"
; otherwise, the value ofobj.toString()
is returned.
So there shouldn't really be a difference except for an additional method invocation.
Also, in the case of Object#toString
, if the instance is null
, a NullPointerException
will be thrown, so arguably, it's less safe.
public static void main(String args[]) {
String str = null;
System.out.println(String.valueOf(str)); // This will print a String equal to "null"
System.out.println(str.toString()); // This will throw a NullPointerException
}
What's the difference between String(value) vs value.toString()
They are not completely the same, and actually, the String constructor called as a function (your first example), will at the end, call the toString
method of the object passed, for example:
var o = { toString: function () { return "foo"; } };
String(o); // "foo"
On the other hand, if an identifier refers to null
or undefined
, you can't use the toString
method, it will give you a TypeError
exception:
var value = null;
String(null); // "null"
value.toString(); // TypeError
The String
constructor called as a function would be roughly equivalent to:
value + '';
The type conversion rules from Object-to-Primitive are detailed described on the specification, the [[DefaultValue]]
internal operation.
Briefly summarized, when converting from Object-to-String, the following steps are taken:
- If available, execute the
toString
method.- If the
result
is a primitive, returnresult
, else go to Step 2.
- If the
- If available, execute the
valueOf
method.- If the
result
is a primitive, returnresult
, else go to Step 3.
- If the
- Throw
TypeError
.
Given the above rules, we can make an example of the semantics involved:
var o = {
toString: function () { return "foo"; },
valueOf: function () { return "bar"; }
};
String(o); // "foo"
// Make the toString method unavailable:
o.toString = null;
String(o); // "bar"
// Also make the valueOf method unavailable:
o.valueOf = null;
try {
String(o);
} catch (e) {
alert(e); // TypeError
}
If you want to know more about this mechanism I would recommend looking at the ToPrimitive
and the ToString
internal operations.
I also recommend reading this article:
- Object-to-Primitive Conversions in JavaScript
Join() vs toString() vs valueOf() in Javascript
toString
is a method that you can find not only in Array
s, but in every object.
join
allows you to convert every element of the Array
object in to a string, and joining together using a separator. It behaves just like toString
for Array
s, but you can also specify the separator:
var classes = ["first", "second"];
classes.join(" "); // "first second"
toString() in JavaScript: why does toString() still get called since a valueOf() prototype for type conversion of object to number
Since
+obj
requires a number, shouldn't it use thevalueOf()
prototype for type conversion which returns the object.
It actually does call the valueOf
method. But since - as you say - it returns an object, not a primitive value, it is found useless. Then, the alternative is called: toString()
, which does return a primitive value that is subsequently cast to a number.
You can try
const obj1 = { valueOf() { console.log("valueOf 1"); return this; }, toString() { console.log("toString 1"); return "1"; },};console.log(+obj1);
const obj2 = { valueOf() { console.log("valueOf 2"); return 2; }, toString() { console.log("toString 2"); return "2"; },};console.log(+obj2);
Does valueOf always override toString in javascript?
The + operator on Date objects uses toString not valueOf. Also if valueOf returns a non-primitive value then the toString method is called next. (JavaScript - The definitive guide, section 3.14) Using your example:
var result = "4" + {
toString: function () {
return "4";
},
valueOf: function () {
return this; // returning an object, not a primitive
}
};
Result is now 44.
Application area of toString() and valueOf() method
toString
converts a value to a string, valueOf
converts it to a number. Exactly which one is called depends on the context in which you're asking.
If javascript is expecting a string or trying to coerce the object to a string, it will use toString. If it is expecting a number it will use valueOf.
the exception to this rule is that when a value has both a toString and a valueOf, it always calls valueOf.
var x = {
toString: function(){
return "x";
},
valueOf: function(){
return 2;
}
}
alert("String :"+x); //2
alert("Number :"+(0+x)); //2
fiddle: http://jsfiddle.net/DsGKf/
So be careful about defining valueOf on things that you want to have act as strings.
Difference between value.toString and value.toString()
value.toString() -> It will convert any value to string and return that value.
value.toString -> It will work as a primitive value and it will create an object wrapper. That's why it will not give any error or warning instead it will return a reference to the toString method.
So in short value.toSting() will return a string and value.toString will return a reference to the toString method.
About javascript function valueOf\toString and 'curry' function behaved differently in Chrome,Firefox and node enviroment
At first you can beautify the whole code a bit:
function add(..arr){
function fun(...args){
arr.push(...args);
return fun
}
fun.toString = function(){
return arr.reduce((total, num) => total + num)
};
return fun;
}
And as you noticed correctly, logging a function is completely up to the environment. Firefox and Node return the code of the function, while Chrome does sth like:
out( "f" + add.toString())
so our toString function gets called and something is logged. To have a consistent behaviour between the different environments we could call toString explicitly:
console.log(add(1)(2)(3).toString());
This can be inferred:
console.log("" + add(1)(2));
Related Topics
Bitwise or in Ruby VS JavaScript
Maintain Model of Scope When Changing Between Views in Angularjs
Reading JavaScript Variable into Shiny/R on App Load
How to Use Source: Function()... and Ajax in Jquery UI Autocomplete
How Should Look a Application.Scss File in Ruby
React - Changing an Uncontrolled Input
How to Parse JavaScript Using Nokogiri and Ruby
How to Detect When a Youtube Video Finishes Playing
What's the Difference Between Console.Dir and Console.Log
Slow Assets Compilation in Development Mode
How to Set Header and Options in Axios
Accessing ASP.NET Controls Using Jquery (All Options)
Wicketpdf Rendering Table Not Aligned Properly and Footer Place at Last Page
How to Implement Jquery.Noconflict()