碰到过几次这两个的问题了,于是总结一下,通过几个例子来学学toString() 和 valueOf() 以及他们之间的区别
目录:
零、隐式转换
一、认识toString
二、认识valueOf()
三、toString() vs valueOf
零、隐式转换
Point to: 有趣的JS隐式转换
一、认识toString()
MDN:toString() 方法返回一个表示该对象的字符串。
Point to MDN: toString()
1.每个对象都有一个 toString() 方法,当对象被表示为文本值时或者当以期望字符串的方式引用对象时,该方法被自动调用。对对象x,toString() 返回 “[object type]”,其中type是对象类型。如果x不是对象,toString() 返回x应有的文本值(不是单纯的加”“)
var x = {}; console.log(x.toString()); // [object Object] //特别的用法 toString.call(new Date); // [object Date] toString.call(new String); // [object String] toString.call(Math); // [object Math] //Since JavaScript 1.8.5 toString.call(undefined); // [object Undefined] toString.call(null); // [object Null] //其他类型的toString(): var x = [1,2,3]; x.toString(); //返回'1,2,3' var x = function(){console.log('lalala')} x.toString();// 返回'function(){console.log('lalala')}' var x = 12345; x.toString();// 返回'12345'
2.可以自己定义一个对象的toString()方法来覆盖它原来的方法。这个方法不能含有参数,方法里必须return一个值。
var a = {}; console.log(a.toString());//输出[object Object] a.toString = function() {return "a new toString"}; console.log(a + " hello" );//输出a new toString hello console.log(a + 1);//输出a new toString1
二、认识valueOf()
MDN:valueOf() 方法返回指定对象的原始值
Point to MDN: valueOf()
1.javascript 调用 valueOf() 方法用来把对象转换成原始类型的值(数值、字符串和布尔值)
默认情况下, valueOf() 会被每个对象Object继承。每一个内置对象都会覆盖这个方法为了返回一个合理的值,如果对象没有原始值,valueOf() 就会返回对象自身
//一下例子均没有原始值,返回这个对象本身 var x = {}; x.valueOf(); // 返回 Object {} var x = [1,2,3]; x.valueOf(); //返回[1, 2, 3] var x = function(){console.log('lalala')} x.valueOf();// 返回 function (){console.log('lalala')} var x = 12345; x.valueOf();// 返回 12345
2.可以自己定义一个对象的valueOf()方法来覆盖它原来的方法。这个方法不能含有参数,方法里必须return一个值。
var x = {}; x.valueOf = function(){ return 10; } console.log(x+1);// 输出10 console.log(x+"hello");//输出10hello
三、toString() vs valueOf()
1.如果一个对象它的toString() 和 valueOf()方法均存在时,到需要调用的时候,引用哪一个方法?
看下面的问题:
//这个对象是一个函数 function fn() { return 20; } console.log(fn + 10); console.log(fn + 'hello'); fn.toString = function() { return 10; } console.log(fn + 10); console.log(fn + 'hello'); fn.valueOf = function() { return 5; } console.log(fn + 10); console.log(fn + 'hello'); // 输出结果分别是多少?
输出结果如下:
function fn() { return 20; }10 function fn() { return 20; }hello 20 10hello 15 5hello
从上面的结果我们可以看出:当函数fn用+连接一个字符串或者是数字的时候,如果我们没有重新定义valueOf和toString,其隐式转换会调用默认的toString()方法,将函数本身内容作为字符串返回;
如果我们自己重新定义toString/valueOf方法,那么其转换会按照我们的定义来,其中valueOf比toString优先级更高
2.再看下一个问题:如果这个对象不是函数呢?
经测试,如果这个对象是object/数组/,结果和上面的一样 ;
但如果这个对象是Date,则都调用toString();
var x = new Date(0); //"Thu Jan 01 1970 08:00:00 GMT+0800 (马来西亚半岛标准时间)" x.toString(); //"Thu Jan 01 1970 08:00:00 GMT+0800 (马来西亚半岛标准时间)" x.valueOf(); //0 x+1; //"Thu Jan 01 1970 08:00:00 GMT+0800 (马来西亚半岛标准时间)"
3.第三个问题,上面讨论了这个对象本身的类型的影响,下面讨论一些特殊情况
var x = { toString: function () { return "foo"; }, valueOf: function () { return 42; } }; alert(x); // foo "x=" + x; // "x=42" x + "=x"; // "42=x" x + "1"; // 421 x + 1; // 43 ["x=", x].join(""); // "x=foo"
可以看到+时,和上面的结论一样,但是alert , [x].join(“”)等这类特殊的表达,均调用toString(),当作特例记住就行了