初学者跪着学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大全


<<:  从零开始学3D游戏设计:自定义粒子效果

>>:  Day28. Rails 搭配 DataTable 写出完美的列表页

零信任即存取控制2.0 (Zero Trust as Access Control 2.0)

零信任(Zero Trust) 这个名词已经出现了十年。如果您使用Google进行搜索,则会有大量...

推论 & 聚合( Inference and Aggregation)

-聚合功能 分区(Partitioning) 对数据或数据库进行分区是指将数据集分成多个部分并分别...

[Day 27] 那些年欧洲退税的鸟事

去了 4 次,每次总是要买点东西才回家XDD 越买越大包,这就是另一件事情了... 有鉴於 4 次...

如果我是主力,我会怎样割韭菜

所谓的主力,就是有绝对多的资金,或是大量持有某一档股票,最大的优势就是容易操控股票价格。 今年一堆散...

DAY28-EXCEL统计分析:回归分析介绍

回归分析 回归分析的主要目的是为了探讨一个或多个自变数和一个因变数间的关系,利用方程序来解释资料或预...