一 对象转换为字符串(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 转换为字符串的方法,但它们之间有一些细微的差别和适用场景。
-
方法来源:
obj.toString()
是对象obj
上的方法,如果obj
是自定义对象且没有重写toString()
方法,那么它将调用从Object.prototype
继承的默认toString()
方法。对于内置对象(如数组、函数、日期等),它们通常有自己的toString()
实现。String(obj)
是一个全局函数,它可以将任何类型的值转换为字符串。这个函数内部会尝试调用对象的toString()
方法(如果对象有的话),但也可能使用其他机制来确保正确的转换。
-
null 和 undefined 的处理:
- 如果
obj
是null
或undefined
,调用obj.toString()
会导致运行时错误(因为null
和undefined
没有方法)。 String(null)
返回字符串"null"
,String(undefined)
返回字符串"undefined"
。
- 如果
-
自定义对象的处理:
- 对于自定义对象,如果重写了
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)
}
根据规则比对结果,完全符合
对象转数字
这里只讲一下自定义对象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)
ok,结果也符合规则。
这篇文章提到的类型转换还不够全面,想要更加全面和深入了解类型转换的掘友可以去阅读
冴羽老师
JavaScript深入之头疼的类型转换(上)在 JavaScript 中,有一部分内容,情况复杂,容易出错,饱受争议但 - 掘金 JavaScript深入之头疼的类型转换(下)这其实是因为 JavaScript 自动的将数据类型进行了转换,我们通常称 - 掘金