0

This question is based on previous question:

Difference in these 2 Strings (JavaScript)

The people replied that there is a difference by creating string via 2 separate ways:

  1. String Literal creates string (var a = "abc")
  2. new keyword creates string-object, I assume it is a kind of object (var b = new String("def"))

Now, typeof in 1st case will return string. In 2nd case it will return Object. I am okay, there might be certain way of working, of JS engine, by the people who developed it.

But, then, in the following example why the hell I am getting the answer in last line as abcdef. Now, that too should have consoled [object][object], as the line above. Now I am really confused, new String is either creating a string, or object or what? It is just NOT consistent!

Can someone help me explain?

var obj1 = new Object({name: "Peter"});
var obj2 = new Object({age: 29});
var str1 = new String("abc");
var str2 = new String("def");
console.log(obj1);
console.log(obj2);
console.log(str1);
console.log(str2);
console.log(obj1 + obj2);
console.log(str1 + str2); 
Deadpool
  • 7,811
  • 9
  • 44
  • 88

2 Answers2

2

new String creates a String object, which inherits from Object, but has its own .toString and .valueOf methods, so it will print the string content.

var o = new Object();
var s = new String("foo");

console.log(o.toString === s.toString); // false
console.log(o.valueOf === s.valueOf);   // false

You can override them with your own to see that they're invoked. Just be sure to invoke the originals too.

var s = new String("foo");

s.valueOf = function() {
    console.log("custom valueOf");
    return String.prototype.valueOf.call(this);
}
s.toString = function() {
    console.log("custom toString");
    return String.prototype.toString.call(this);
}

console.log(s + s);
[""].join(s);
  • Yep, but I have not used anywhere .toString() or .valueOf(). I am adding 2 Objects. There is no sense, or any code-conversion line. – Deadpool Sep 07 '20 at 05:35
  • 1
    @Deadpool It's the `+` operator making an internal conversion, as concatenating two objects with `+` wouldn't make sense. – Teemu Sep 07 '20 at 05:36
1

But, then, in the following example why the hell I am getting the answer in last line as abcdef. Now, that too should have consoled [object][object], as the line above.

The difference is a String object has a default valueOf method that returns the string value contained within the object.

The Object object has a more generic valueOf method which simply returns a string of [object Object]

See -

const one =
  { valueOf: _ => 1 }
  
const two =
  { valueOf: _ => 2 }
  
console.log(one + two)
// 3

You can define valueOf to be anything -

const foo =
  { valueOf: _ => "foo" }
  
const bar =
  { valueOf: _ => "bar" }
  
console.log(foo + bar)
// "foobar"
Mulan
  • 129,518
  • 31
  • 228
  • 259
  • Ok, so the whole story is about -- "speically developed .valueOf()" which always runs, whether we know or not, and is -- coded differently for `new String(), new Number, new BigInt, new Boolean()`. But for `new Object` it has not been developed in the same manner? Is it. – Deadpool Sep 07 '20 at 05:37
  • no you almost never use `+` to add objects together. JavaScript `+` works for strings and numbers but operator overloading is not supported. so you have named methods like `Array.prototype.conat` instead of `[1] + [2]`. `valueOf` is a special fallback case where your object is getting dynamically coerced and you have an opportunity to try to output some reasonable value. in practice though you want to define behaviours and not rely on `valueOf`. – Mulan Sep 07 '20 at 05:39