> For the complete documentation index, see [llms.txt](https://mistborn.gitbook.io/til-coding/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mistborn.gitbook.io/til-coding/javascript/object-to-primitive-conversion.md).

# Object to primitive conversion

1\. 所有的物件轉換布林值皆為 true。2. Date 物件用運算符號會轉換為數字類型。3. 用 alert 等等輸出，物件會轉換為字串。

## ToPrimitive

轉換為字串或數字得的演算法為 `ToPrimitive`，物件被使用在需要原始值的情況時，會自動轉換。

```javascript
//String
// output
alert(obj);

// using object as a property key
anotherObj[obj] = 123;

// number
// explicit conversion
let num = Number(obj);

// maths (except binary plus)
let n = +obj; // unary plus
let delta = date1 - date2;

// less/greater comparison
let greater = user1 > user2;

// default
// binary plus
let total = car1 + car2;

// obj == string/number/symbol
if (user == 1) { ... };

// 除了 Date 物件，所有 default 都和 number 轉換一致，可視為只有 2 種轉換，number and string
```

JavaScript 有 3 種轉換類型的方法

1. Call `obj[Symbol.toPrimitive](hint)` if the method exists,
2. Otherwise if hint is `"string"`
   * try `obj.toString()` and `obj.valueOf()`, whatever exists.
3. Otherwise if hint is `"number"` or `"default"`
   * try `obj.valueOf()` and `obj.toString()`, whatever exists.

## Symbol.toPrimitive

```javascript
obj[Symbol.toPrimitive] = function(hint) {
  // return a primitive value
  // hint = one of "string", "number", "default"
}

let user = {
  name: "John",
  money: 1000,

  [Symbol.toPrimitive](hint) {
    alert(`hint: ${hint}`);
    return hint == "string" ? `{name: "${this.name}"}` : this.money;
  }
};

// conversions demo:
alert(user); // hint: string -> {name: "John"}
alert(+user); // hint: number -> 1000
alert(user + 500); // hint: default -> 1500
```

## toString/valueOf

`toString` and `valueOf` 來自上古時代，如果沒有 `Symbol.toPrimitive` ，JavaScript 會尋找這 2 種方法來轉換類型。

```javascript
let user = {
  name: "John",
  money: 1000,

  // for hint="string"
  toString() {
    return `{name: "${this.name}"}`;
  },

  // for hint="number" or "default"
  valueOf() {
    return this.money;
  }

};

alert(user); // toString -> {name: "John"}
alert(+user); // valueOf -> 1000
alert(user + 500); // valueOf -> 1500

// 只想要一個可以轉換成原始值的方法，用 toString
let user = {
  name: "John",

  toString() {
    return this.name;
  }
};

alert(user); // toString -> John
alert(user + 500); // toString -> John500
```

## Further operations

原始值轉換不一定返回 hint 的值，沒有限制 `toString` 一定要返回 string 或 hint 是 number`Symbol.toPrimitive` 一定返回 number，唯一的事實是一定會返回原始值。

```javascript
// number
let obj = {
  toString() { // toString handles all conversions in the absence of other methods
    return "2";
  }
};

alert(obj * 2); // 4, ToPrimitive gives "2", then it becomes 2

// string
let obj = {
  toString() {
    return "2";
  }
};

alert(obj + 2); // 22 (ToPrimitive returned string => concatenation)

// number
let obj = {
  toString() {
    return true;
  }
};

alert(obj + 2); // 3 (ToPrimitive returned boolean, not string => ToNumber)
```
