js中的valueOf和toString

valueOf和toSring两个函数是除null和undefined两种数据类型以外其他五种数据类型(number/string/bool/object/symbol)原型链上共有的函数,那么这两个函数主要是用来干什么的呢?司徒正美大神给出的答案是:值运算和显示问题,一般在隐式类型转换时会自动调用(经典面试题见备注3)。
例1:
如果同时重写了valueOf和toString方法:

var aaa = {
  i: 10,
  valueOf: function() { 
	  console.log('valueOf')
	  return this.i+30; 
  },
  toString: function() { 
	  console.log('toString')
	  return this.i+10;
   }
}
 console.log(aaa > 20); // valueOf  true
 console.log('' + aaa);  //  valueOf  40
 console.log(++aaa); // valueOf  41
 console.log(+aaa); //  valueOf  40
 alert(aaa); // toString 20
 console.log(aaa == 40) //valueOf true
 console.log(String(aaa)) // toString 20

总结:涉及到操作符的问题,valueOf的优先级比toString的优先级高,涉及到显示问题,toString方法优先级比valueOf方法高。
例2:
如果只是重写了toString方法:

var aaa = {
  i: 10,
  toString: function() { 
	  console.log('toString')
	  return this.i+10;
   }
}
 console.log(aaa > 20); // toString false
 console.log('' + aaa);  //  toString 20
 console.log(++aaa); // toString 21
 console.log(+aaa); //  toSring 20
 alert(aaa); // toString 20
 console.log(aaa == 20) //toString true
 console.log(String(aaa)) // toString 20

总结:只重写了toString方法的话,toString方法比原型链上的valueOf方法优先级高。
例3
如果只重写了valueOf方法:

var aaa = {
  i: 10,
  valueOf: function() { 
	  console.log('valueOf')
	  return this.i+30;
   }
}
 console.log(aaa > 20); // valueOf true
 console.log('' + aaa);  //  valueOf 40
 console.log(++aaa); // valueOf 41
 console.log(+aaa); //  valueOf 40
 alert(aaa); // [object Object]
 console.log(aaa == 20) //valueOf false
 console.log(String(aaa)) // [object Object]

总结:只重写了valueOf方法的话,涉及到值运算优先调用valueOf方法,涉及到显示问题还是优先调用原型链上的toString方法。
参考:https://www.cnblogs.com/rubylouvre/archive/2010/10/01/1839748.html

备注(针对一般没有对valueOf和toString方法进行重写的情况):

  1. 对除null和undefined(这两种类型的原型上没有valueOf方法)以外的数据类型调用valueOf方法,得到的都是数据本身。
var a = 1
var aa = a.valueOf()
aa === a //true

var b = 'a'
var bb = b.valueOf()
bb ===b //true

var c = true
var cc = c.valueOf()
cc === c //true

var obj = {name: 'age'}
var objobj = obj.valueOf()
obj === objobj //true

var s = Symbol()
var ss = s.valueOf()
ss === s //true
  1. 对number/string/bool/symbol类型数据调用toString方法得到的是对应的字符串,对object类型数据调用toString的方法得到的是"[object Object]",null和undefined两种数据类型的原型链上没有toString方法。
var aaa = a.toString() // "1"
var bbb = b.toString() // "a"
var ccc = c.toString() // "true"
var objobjobj = obj.toString() //"[object Object]"
var sss = s.toString() //"Symbol()"


3. 也可以得到一个经典前端面试题的一种解法
如何能够使得下列的表达式返回true

a==1 && a==2 && a==3

解法如下:

var a = {
	i: 1,
	valueOf: function() {
		return a.i++
	}
}
a==1 && a==2 && a==3 //返回true

以上重写了valueOf函数,比较运算时会优先调用该函数。当然,如果重写toString方法的话,比较运算也会优先调用该toString函数,因此可以到达同样的效果。

还有其他一种常见的解法:

var val = 1
Object.defineProperty(window, 'a', {
	get() {
		return val++
	}
})
a==1 && a==2 && a==3 //同样返回true
  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值