iT邦幫忙

2021 iThome 鐵人賽

DAY 13
0
Modern Web

初學者跪著學JavaScript系列 第 13

初學者跪著學JavaScript Day13 : 物件加字串?物件加物件?

想不到吧~加法還可以寫第二篇
延續昨天相加:{}+{},{}+[],[]+{},[]+[] 到底是什麼?
{name:'wendy'}+'apple' 可以加嗎?

一日客語:中文:烤肉醬,客語:烤niu ㄐㄩㄥ.

要先知道objects 轉成 primitive values 這件事

先知道哪些是Primitive values:原型七大值(自己取的)
Number、String、Boolean 、Null、Undefined、Symbol、BigInt
之前寫的Primitive和Non-primitive 連結

先前提要

這四種情況會轉成primitive values
1.物件對boolean轉換
2.物件對字串轉換
3.物件對數字的轉換
4.特例的運算子轉換:{name:'wendy'}+'apple'

物件轉成原始值(primitive values)的演算法有這三種
prefer-string:回傳是 primitive values,對字串轉換是可能就使用字串。
prefer-number:回傳是 primitive values,轉換可能就使用數字。
prefer-no-preference(無偏好):Date是使用prefer-string,其他是使用prefer-number


轉換方式:toString()、valueOf() 使用順序是根據演算法

toString()

回傳:返回物件字串表示法

個類別的toString()方法,定義方式不同,也可以自己定義

object toString()
array 陣列裡的元素連逗號會一起轉成字串
RegExp 回傳RegExp字面值
object 回傳[object Object]
date 回傳日期與時間

array 的toString()

陣列裡的元素轉成字串

let b =[1,2,3,4,5]
b.toString() //'1,2,3,4,5'

Date 的toString()

回傳日期與時間的字串

let c = new Date()  //c會是一個物件
c.toString()
//'Mon Sep 27 2021 14:24:51 GMT+0800 (台北標準時間)'

RegExp的toString()

回傳RegExp字面值Literals

let d = /[\u0400-\u04FF]+/g
d.toString()
//'/[\u0400-\u04FF]+/g'

物件的toString()

回傳[object Object]

const d = {apple:'red'}
d.toString()
//'[object Object]'

valueOf

回傳:
string、Number、boolean 會返回原始值
陣列、function、物件會返回物件本身

返回值:就是原始值primitive values

Type 返回值
string 返回值
Number 返回值
boolean 返回值
date 回傳從1970到現在的毫秒數
array 物件自己
function 物件自己
object 物件自己

返回值:

const myString = new String('test');
const myNumber = new Number(42);
const myDate = new Date();
console.log('myString:', myString.valueOf());//test
console.log('myNumber:', myNumber.valueOf());//42
console.log('myDate:', myDate.valueOf());//1559347200000

返回物件本身

function MyFunction(value) {
    this.name = value;
}
const myArray = [100, 20];
const myArray2 = ['apple', { apple: 'apple' }];
const myFunction = new MyFunction('wendy');
const myReg = /[\u0400-\u04FF]+/g;
console.log('myArray:', myArray.valueOf());//[100,200]
console.log('myFucntion:', myFunction.valueOf());// MyFunction { name: 'wendy' }
console.log('myReg:', myReg.valueOf());// /[\u0400-\u04FF]+/g

*只寫出部分type 的toString()和valueof()

在Object.prototype提供toString()、valueOf()方法

三種演算法

prefer-string

  1. toString()
    若有toString()且回傳原始值,使用原始值;
    若沒有toString()或toString()回傳object,則嘗試valueOf()方法(下一步)。
  2. valueOf()
    有valueOf()且回傳原始值,使用該原始值;否則回報TypeError。

prefer-number

順序

  1. valueOf()
  2. toString()

no-preference(無偏好)

除了Date物件會prefer-string,其他物件prefer-number


物件對boolean轉換

  • 所有物件都會轉成true 但不會用到上面那三個演算法
let a = new Boolean(false)
console.log(Boolean(a)) //true

物件對字串轉換

  • 使用prefer-string 演算法:toString() -> valueOf()
let myobject = [1, 2, 3];
console.log(String(myobject));//1,2,3
let myobject2 = { name: 'wendy' };
console.log(String(myobject2));//[object Object]

物件對數字的轉換

  • 使用prefer-number演算法:valueOf() -> toString()
let myNumber = new Number(20)
console.log(Number(myNumber))//20

特例的運算子轉換

JS當有物件會使用no-preference 演算法轉成原始值

檢查原始值的型別,任一個運算元是字串就會把另一個也轉成字串,否則都轉成數字型別。

現在來討論昨天說的

{name:'wendy'}+'apple'

要先知道運算元有物件會使用no-preference

目的:運算元轉成原始值

演算法使用:no-preference

除了Date物件會prefer-string,其他物件prefer-number

左運算元:
1.valueOf():object有valueOf() return 物件自己({name:'wendy'}) 因為不是原始值所以會跑toString()
2.toString()
第一步會走toString():object.toString()會是 return [object Object]

右運算元:
1.valueOf():有valueOf()返回值'apple',是原始值

左元算元+右運算元
*任一個運算元是字串會使另一個運算元轉成字串

左運算元是字串另一個運算元也會轉成字串

使用console.log()印出會是[object Object]apple


小注意

  1. 要注意在瀏覽器直接打會出現NaN,這原因不太清楚囧

2.字面值${value}裡放array和使用雙引號會不一樣
因為字面值會轉toString

console.log(`myArray.valueOf():${myArray.valueOf()}`);//100,200
console.log('myArray.valueOf():', myArray.valueOf());//[100,200]

valueOf和toString可以改自己改寫,相加就會和上面不一樣

如何使用

function fruit(name) {
    this.name = name;
}

fruit.prototype.valueOf = () => {
    return '自己定義的valueOf';
};
fruit.prototype.toString = () => {
    return '自己定義的toString';
};

const myObject = new fruit();
console.log(myObject.valueOf()); //自己定義的valueOf
console.log(myObject.toString()); //自己定義的toString
console.log(myObject + 'add'); //自己定義的valueOfadd
console.log(myObject + {}); //自己定義的valueOf[object Object]

理解以上就可以知道這些了

{}+{}
{}+[]
[]+{}
[]+[]

Eddy思考與學習

js隐式装箱-ToPrimitive

https://262.ecma-international.org/12.0/#sec-tonumeric
瞭解V8(二)型別轉換:V8是怎麼實現1+「2」的?

JS大全


上一篇
初學者跪著學JavaScript Day12 : 麻煩的JS加法
下一篇
初學者跪著學JavaScript Day14 : 創建Array 四種方式
系列文
初學者跪著學JavaScript30

1 則留言

0
MJ
iT邦新手 5 級 ‧ 2021-09-28 11:37:06

依我看,上面倒像蝦子XD

wendy iT邦新手 5 級 ‧ 2021-09-28 21:59:59 檢舉

蝦子跪法

我要留言

立即登入留言