探究JavaScript中的valueOf和toString

JS 中的类型

JS中的类型分为两大类: primitiveobject

primitive: null, undefined, Number, String, Boolean, Symbol。
object:不是primitive类型的值,都是object类型。

JS是非严格类型的语言

在JS中存在大量的数据隐式转换,例如 1 + 'a'。对于primitive类型,在不同类型之间有明确的转换规则:

Number

Number(null) // 0
Number(undefined) // NaN
Number(false) // 0
Number(true) // 1
Number('123') // 123
Number('123a') // NaN
Number('') // 0
Number(Symbol('1')) // TypeError

String

非常直接,将字面量形式直接转换成字符串形式的字面量

String(null) // 'null'
String(undefined) // 'undefined'
String(NaN) // 'NaN'
String(1) // '1'
String(Symbol('a')) // 'Symbol(a)'

Boolean

Boolean(null) // false
Boolean(undefined) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false
/* 其余情况均为true */
Boolean('a') // true
Boolean(Symbol('foo')) // true

如果是类型转换涉及到object类型呢

primitive转成object

将primitive类型转成object类型都有对应的构造函数。

Number(1)
String('foo')
Boolean(true)

将object转换成primitive

在ECMAScript文档,为object定义了一个内部方法toPrimitive。它类似于下面的形式

toPrimitive(target, PreferredType?)

target表示需要转换的对象,PreferredType参数可选,标明想要转成的类型,string 或 number。
转换步骤:

  1. 如果没有定义PreferredType, 则默认为’default’;
  2. 如果存在自定义的toPrimitive方法,就返回执行自定义toPrimitive方法的结果;
  3. 如果PreferredType 的值为’default’,默认选择为number
  4. 返回系统默认toPrimitive方法的执行结果;

如果执行系统默认的toPrimitive方法,
在输入对象是object,且 PreferredType的值为’string’,则优先执行toString方法,没有则执行valueOf方法。
如果PreferredType的值为’number’,则优先执行valueOf方法,没有valueOf方法则执行toString方法。

js中的操作符大部分都是针对primitive类型设计的,如果用这些操作符对object类型进行处理运算,会将object类型先转成primitive类型的值,然后在进行运算操作。

+[12] // 12
+({}) // NaN
[]==0 // true
{}==0 // false

上述情况走的都是对象自身默认的toPrimitive方法且未指定PreferredType值。
还有一种情况是我们自定义对象的valueOf和toString方法。

var o = {
    value:1,
    toString:function(){
        console.log('toString');
        return 'one';
    },
    valueOf: function(){
        console.log('valueOf');
        return this.value++;
    }
}

alert(o); // 'one'
console.log(o == 1); // true
console.log(o == 2); // true
对象默认的toString和valueOf方法

这两个方法都在Object.prototype上面。valueOf默认返回对象自身,如果操作对象是基本类型,则只返回一个基本值。怎么理解这句话呢?

(1).valueOf() // 1
var n = new Number(1); 
n.name="number";
console.log(n);

var m = n.valueOf();
var o = { name: 'object'};
var p = o.valueOf();
console.log(m);
console.log(p);

toString的返回值就比较

ES6中的Symbol.toPrimitive
var o = {
    value:1,
    [Symbol.toPrimitive]: function(hint){
        console.log('Symbol.toPrimitive');
        if(hint === 'number' || hint === 'default') return this.value+=2;
        return 'toprimitive function';
    },
    toString:function(){
        console.log('toString');
        return 'one';
    },
    valueOf: function(){
        console.log('valueOf');
        return this.value++;
    }
}

alert(o); // 'toprimitive function'
console.log(o == 1); // false
console.log(o == 5); // true

ToPrimitive 定义(https://www.ecma-international.org/ecma-262/6.0/#sec-toprimitive)

Data类型的toPrimitive

toPrimitive中还存在另外一个特殊情况。Date类型的对象在执行toPrimitive方法时,PreferredType的默认值为’string’,而非’number’。
下面例子中,明显表明 Date类型在执行 +1操作时,先转成字符串再进行运算; 而普通对象则是先执行valueOf方法,再进行运算;

var d = new Date;
var o = {
    value: 1,
    valueOf: function(){ return 2;},
    toString: function(){ return 'tostring';}
}
d+1;// "Sun Dec 15 2019 21:56:35 GMT+0800 (中国标准时间)1"
o+1; // 3
d.toString=function(){return 'date toString';}
console.log(d); // "date toString"
d+1;// "date toString1"

Summary

valueOftoString是JS中类型转换中处理object类型的重要组成。

在未自定义的情况下,这两个方法都在Object.prototype上。 valueOf通常返回对象本身,而toString会根据对象的internal slot返回数据格式如下[object ${Type}]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值