类型转换:对象转字符串和数字

95 阅读6分钟

一 对象转换为字符串(String

当你尝试将一个对象转换为字符串时,JavaScript会调用对象的 toString() 方法。如果没有自定义的 toString() 方法,则使用默认的 Object.prototype.toString() 方法。当然了这里需要说的是像函数、数组、日期和RegExp(正则表达式)这些特殊的对象是有内置的toString()方法的。

  • 数组的 toString() 方法将元素转换为字符串并用逗号分隔。
  • 函数的 toString() 方法返回函数的源代码字符串表示。
  • 日期对象的 toString() 方法返回一个表示该日期的字符串,格式因实现而异
  • RegExp 对象的 toString() 方法用于返回正则表达式的字符串表示形式

那么好上代码辅助理解:

console.log(Object.prototype.toString.call({a:1}));//[object Object]
console.log(({a:1}).toString());//[object Object],因为这个对象没有自己的toString()方法所以使默认的 `Object.prototype.toString()` 方法和1使用的方法是相同的
console.log([1,2,3].toString());//1,2,3
console.log((function(){var a = 1;}).toString())//function(){var a = 1;}
console.log(new Date().toString())//输出类似于: "Wed Oct 04 2023 14:48:00 GMT+0000 (Coordinated Universal Time)"
console.log(/abc-123/gi.toString())//  输出/abc-123/gi

了解一下Object.prototype.toString()

Object.prototype.toString() 方法在被调用时,如果直接使用(即不通过 call 或 apply 改变其 this 上下文),则会返回 "[object Object]",这里的 "Object" 是指 Object 构造函数的名字,而第一个 "object" 是固定的字符串前缀,用于标识这是一个对象类型的字符串表示。

但是,当通过 call 或 apply 方法调用 Object.prototype.toString,并传入不同的对象作为 this 值时,它会根据传入对象的实际类型返回不同的字符串。例如:

对于普通对象(非内置对象,如用户自定义的对象),它会返回 [object Object]。 对于数组,它会返回 "[object Array]"。 对于函数,它会返回 "[object Function]"。 对于日期对象,它会返回 "[object Date]"。

继续上代码

console.log(Object.prototype.toString.call({a:1}));//[object Object]
console.log(Object.prototype.toString.call([1,2]));//[object Array]
console.log(Object.prototype.toString.call(function(){var a = 1;}))//[object Function]
console.log(Object.prototype.toString.call(new Date()))//[object Date]

了解一下obj.toString() 和 String(obj)

obj.toString() 和 String(obj) 都是将对象 obj 转换为字符串的方法,但它们之间有一些细微的差别和适用场景。

  1. 方法来源

    • obj.toString() 是对象 obj 上的方法,如果 obj 是自定义对象且没有重写 toString() 方法,那么它将调用从 Object.prototype 继承的默认 toString() 方法。对于内置对象(如数组、函数、日期等),它们通常有自己的 toString() 实现。
    • String(obj) 是一个全局函数,它可以将任何类型的值转换为字符串。这个函数内部会尝试调用对象的 toString() 方法(如果对象有的话),但也可能使用其他机制来确保正确的转换。
  2. null 和 undefined 的处理

    • 如果 obj 是 null 或 undefined,调用 obj.toString() 会导致运行时错误(因为 null 和 undefined 没有方法)。
    • String(null) 返回字符串 "null"String(undefined) 返回字符串 "undefined"
  3. 自定义对象的处理

    • 对于自定义对象,如果重写了 toString() 方法,那么 obj.toString() 会调用这个重写的方法。
    • String(obj) 在处理自定义对象时,也会尝试调用 obj.toString(),但如果 toString() 方法返回的不是一个原始字符串(例如,它返回了一个对象),则 String() 函数可能会使用其他方式来转换对象(例如,通过调用 [[ToPrimitive]] 内部方法,这可能会尝试调用 valueOf() 方法,如果 valueOf() 也返回对象,则最终会回退到默认的转换逻辑)。

那么好,举例细说一下自定义对象处理

先了解一下对象转换为基本类型的另一个方法valueOf():

valueOf() 方法是一个可以从许多内置对象类型上调用的方法,包括函数、数组、日期和普通对象。这个方法的行为取决于被调用对象的类型。下面是对不同类型对象调用 valueOf() 方法时的转换结果:

函数(Function): 当在函数上调用 valueOf() 方法时,它通常返回函数本身。这是因为函数在 JavaScript 中也是对象,而默认情况下,对象的 valueOf() 方法返回对象本身(除非被重写)。

数组(Array): 数组的 valueOf() 方法也返回数组本身。这是因为数组是特殊的对象,它们的 valueOf() 方法没有被重写为返回其他类型的值。

日期(Date): 日期的 valueOf() 方法返回一个数字,表示自 1970 年 1 月 1 日 00:00:00 UTC 以来的毫秒数。这个数字是日期的时间戳表示。

普通对象(Object): 对于普通对象(即不是函数、数组、日期等特殊类型的对象),valueOf() 方法默认返回对象本身。这是因为对象的 valueOf() 方法通常没有被重写,而它继承自 Object.prototype.valueOf(),该方法返回调用它的对象。

了解了valueOf()方法那就好理解下面的自定义对象处理了(Obj转为String) 规则就是当自定义对象obj转换为字符String类型时:

1、首先调用对象obj的toString()方法,如果该方法返回一个原始值,js就会将其转换为字符串并将其返回

2、如果toString不存在或者返回的不是原始值,那么就继续调用valueOf()方法,同样的如果该方法返回原始值,js将它转为字符串并返回。

3、如果valueof()也不存在或者返回的不是原始值,js就会抛出异常

我天,你在说什么,别急上代码

let objWithStringValue = {
    toString: function() {
      return "hello"
    }
  }
  
  console.log("情况一:"+String(objWithStringValue))

  let objWithValueOf = {
    toString: function() {
      return this
    },
    valueOf : function(){
        return 2
    }
  }

  console.log("情况二:"+String(objWithValueOf))

  let objWithoutPrimitive = {
    toString: function() {
        return this
      },
      valueOf : function(){
          return this
      }
  }
  try{
      console.log("情况三"+String(objWithoutPrimitive))
  }catch(e){
      console.log(e)
  }

image.png

根据规则比对结果,完全符合

对象转数字

这里只讲一下自定义对象obj转数字Number的处理和上面obj转String规则相似,唯一不同的是,转数字的时候先找的是ValueOf()方法而不是toString():

1、首先调用对象obj的valueOf()方法,如果该方法返回一个原始值,js就会将其转换为数字并将其返回

2、如果valueOf()不存在或者返回的不是原始值,那么就继续调用toString()方法,同样的如果该方法返回原始值,js将它转为数字并返回。

3、如果toString()也不存在或者返回的不是原始值,js就会抛出异常

上码上码:

let specialObj = {
    valueOf:function(){
        console.log("Calling valueOf...")
        return 123;

    },
    toString:function(){
        return "456"
    }
}


console.log(Number(specialObj));// 转数字,找到valueOf

let objectWithoutPrimitiveValuOf = {
   valueOf:function(){
    console.log("Calling valueOf...")
       return this
   },
   toString:function(){
    console.log("Calling toString...")
    return "798"
   }
}
// to Primitive
console.log(Number(objectWithoutPrimitiveValuOf))


let problemObj = {
    valueOf:function(){
     console.log("Calling valueOf...")
        return this
    },
    toString:function(){
     console.log("Calling toString...")
     return this
    }
 }
try {
    console.log(Number(problemObj))
} catch (error) {
    console.log(error)
   
image.png

ok,结果也符合规则。

这篇文章提到的类型转换还不够全面,想要更加全面和深入了解类型转换的掘友可以去阅读

冴羽老师

JavaScript深入之头疼的类型转换(上)在 JavaScript 中,有一部分内容,情况复杂,容易出错,饱受争议但 - 掘金 JavaScript深入之头疼的类型转换(下)这其实是因为 JavaScript 自动的将数据类型进行了转换,我们通常称 - 掘金

u=1379478407,35950780&fm=253&fmt=auto&app=138&f=JPEG.webp