JavaScript的toString()和valueOf()区别到底是什么
2016-07-26 19:20
597 查看
从《JavaScript高级程序设计》这本书里面
[javascript] view
plain copy
var colors = ["red", "blue", "green"]; // 创建一个包含3 个字符串的数组
alert(colors.toString()); // red,blue,green
alert(colors.valueOf()); // red,blue,green
alert(colors); // red,blue,green
的这个例子,我们会有一个非常大的疑问
toString()和valueOf()区别到底是什么?
那么不如看下一个我写的例子
[javascript] view
plain copy
var arr = [1,2,3];
alert(Array.isArray(arr.valueOf()));
alert(Array.isArray(arr.toString()));
猜猜结果是怎么样的?
结果是第一个是true而第二个是false
为什么呢,其实valueOf()调用完以后还是返回一个数组
这个数组被alert的时候会调用toString()函数
所以不是valueOf()和toString()函数相同,而是,根本就是间接的调用了toString()函数!
什么?你不信?
那好吧,我们来测试一下
[javascript] view
plain copy
var arr = [1,2,3];
arr.toString = function () {
alert("你调用了toString函数");
}
alert(arr.valueOf());
(坑爹阿csdn,朕的代码缩进)
来来,猜猜结果。
结果就是我们会看到“你调用了toString函数”。
而对于数值,我们可以调用valueOf的时候直接可以获得数字进行计算,不必转化成字符串,所以不会调用toString
反言之,如果我们需要获得操作对象的字符串形式的时候就会调用其toString函数
举个例子
以下代码来自脚本之家的相关文章
[javascript] view
plain copy
var bbb = {
i: 10,
toString: function() {
console.log('toString');
return this.i;
},
valueOf: function() {
console.log('valueOf');
return this.i;
}
}
alert(bbb);// 10 toString
alert(+bbb); // 10 valueOf
alert(''+bbb); // 10 valueOf
alert(String(bbb)); // 10 toString
alert(Number(bbb)); // 10 valueOf
alert(bbb == '10'); // true valueOf
alert(bbb === '10'); // false
他的文章讲的不是很清楚,为什么在我们重写了代码以后就会出现这样的情况
在这里我说一下我的理解
valueOf的意思是返回最适合该对象类型的原始值,而toString则是将在该对象类型的原始值以字符串形式返回。
第一个
[javascript] view
plain copy
alert(bbb);// 10 toString
这里我们的alert函数需要是的字符串,所以获取的是字符串,而不是原始值,故而调用了toString
第二个
[javascript] view
plain copy
<span style="font-family: Arial, Helvetica, sans-serif;">alert(+bbb); // 10 valueOf</span>
同理,alert要的是字符串不是原始值,其实是+bbb这个东西被调用了toString,而bbb被调用了valueOf
为了验证我们这样写
[javascript] view
plain copy
var a = {
i: 1,
valueOf: function () {
alert("你调用了a的valueOf函数");
return this.i;
},
toString: function () {
alert("你调用了a的toString函数");
return this.i;
}
};
var c = {
i: +a,
valueOf: function () {
alert("你调用了c的valueOf函数");
return this.i;
},
toString: function () {
alert("你调用了c的toString函数");
return this.i;
}
};
alert(c);
其中让c=+a,那么即可知道结果,果然如此,调用了a的valueOf和c的toString
第三个
[javascript] view
plain copy
alert(''+bbb); // 10 valueOf
同理,我们可以把上一段我写的程序里面的c:+a改成c:'’+a
第四个
[javascript] view
plain copy
alert(String(bbb)); // 10 toString
String这个强制转换其实在其内部是调用了传入参数的toString函数……
第五个
[javascript] view
plain copy
alert(Number(bbb)); // 10 valueOf
这个是有区别的,因为bbb的i属性是数值类型的,如果i为11111xxxxx这样的字符串,我们就可以看到调用了bbb的toString了
呐,代码例子
[javascript] view
plain copy
var c = {
i: "11111xxxx",
valueOf: function () {
alert("你调用了c的valueOf函数");
return this.i;
},
toString: function () {
alert("你调用了c的toString函数");
return this.i;
}
};
alert(c);
第六个
[javascript] view
plain copy
alert(bbb == '10'); // true valueOf
这个里面的判等的顺序是,获取原始值,然后判断两边的原始值是否相等,所以调用valueOf
第七个也就是最后一个
[javascript] view
plain copy
alert(bbb === '10'); // false
这个里面的判全等的第一个步骤是判断类型,因为类型都不一样了,所以后面什么都不会调用
讨论
另外,对于原文的这句话“ 在进行对象转换时(例如:alert(a)),将优先调用toString方法,如若没有重写toString将调用valueOf方法,如果两方法都不没有重写,但按Object的toString输出。”我不是很认同
原文例子
[javascript] view
plain copy
var aa = {
i: 10,
toString: function() {
console.log('toString');
return this.i;
}
}
alert(aa);// 10 toString
alert(+aa); // 10 toString
alert(''+aa); // 10 toString
alert(String(aa)); // 10 toString
alert(Number(aa)); // 10 toString
alert(aa == '10'); // true toString
我的观点有些不同,重写了的toString会被未重写的其prototype的valueOf隐式调用,而不是优先调用toString。虽然结果不同,但是其实没有优先级的变化。(但是我只能证明重写了的toString会被未重写的其prototype的valueOf隐式调用,却不能证明未重写和重写后的优先级变化读者如果完成了验证请教教我,我的js上周一才开始学。以下是例子)
[javascript] view
plain copy
var a = {
i: 1,
valueOf: function () {
alert("你调用了a的valueOf函数");
return Object.prototype.valueOf();
},
toString: function () {
alert("你调用了a的toString函数");
return this.i;
}
};
alert(+a);
alert(''+a);
结果的确调用了a的toString和a的valueOf,而我们可以很轻易的从最初的原文例子看到,这两个alert是没有调用国toString的,那么我们即可证明重写了的toString会被未重写的其prototype的valueOf隐式调用。
另一个原文的例子
[javascript] view
plain copy
var bb = {
i: 10,
valueOf: function() {
console.log('valueOf');
return this.i;
}
}
alert(bb);// [object Object]
alert(+bb); // 10 valueOf
alert(''+bb); // 10 valueOf
alert(String(bb)); // [object Object]
alert(Number(bb)); // 10 valueOf
alert(bb == '10'); // true valueOf
而valueOf被重写以后,这个bb的对象没有toString,自然就会调用其prototype的toString,而那个toString的内容必然是
[javascript] view
plain copy
function toString() {
return '[object Object]';
}
,所以其实这个验证并没有什么意义。无论重写哪个函数最终的优先级都没变。
总结
所以那篇的结论并不是最根本的问题,最根本的问题是到底操作对象所处的环境是什么样的。
如果要求的是原始值那么就会调用valueOf,如果要求的是字符串那么就会调用toString。
转自:http://blog.csdn.net/cct418/article/details/50889987
[javascript] view
plain copy
var colors = ["red", "blue", "green"]; // 创建一个包含3 个字符串的数组
alert(colors.toString()); // red,blue,green
alert(colors.valueOf()); // red,blue,green
alert(colors); // red,blue,green
的这个例子,我们会有一个非常大的疑问
toString()和valueOf()区别到底是什么?
那么不如看下一个我写的例子
[javascript] view
plain copy
var arr = [1,2,3];
alert(Array.isArray(arr.valueOf()));
alert(Array.isArray(arr.toString()));
猜猜结果是怎么样的?
结果是第一个是true而第二个是false
为什么呢,其实valueOf()调用完以后还是返回一个数组
这个数组被alert的时候会调用toString()函数
所以不是valueOf()和toString()函数相同,而是,根本就是间接的调用了toString()函数!
什么?你不信?
那好吧,我们来测试一下
[javascript] view
plain copy
var arr = [1,2,3];
arr.toString = function () {
alert("你调用了toString函数");
}
alert(arr.valueOf());
(坑爹阿csdn,朕的代码缩进)
来来,猜猜结果。
结果就是我们会看到“你调用了toString函数”。
而对于数值,我们可以调用valueOf的时候直接可以获得数字进行计算,不必转化成字符串,所以不会调用toString
反言之,如果我们需要获得操作对象的字符串形式的时候就会调用其toString函数
举个例子
以下代码来自脚本之家的相关文章
[javascript] view
plain copy
var bbb = {
i: 10,
toString: function() {
console.log('toString');
return this.i;
},
valueOf: function() {
console.log('valueOf');
return this.i;
}
}
alert(bbb);// 10 toString
alert(+bbb); // 10 valueOf
alert(''+bbb); // 10 valueOf
alert(String(bbb)); // 10 toString
alert(Number(bbb)); // 10 valueOf
alert(bbb == '10'); // true valueOf
alert(bbb === '10'); // false
他的文章讲的不是很清楚,为什么在我们重写了代码以后就会出现这样的情况
在这里我说一下我的理解
valueOf的意思是返回最适合该对象类型的原始值,而toString则是将在该对象类型的原始值以字符串形式返回。
第一个
[javascript] view
plain copy
alert(bbb);// 10 toString
这里我们的alert函数需要是的字符串,所以获取的是字符串,而不是原始值,故而调用了toString
第二个
[javascript] view
plain copy
<span style="font-family: Arial, Helvetica, sans-serif;">alert(+bbb); // 10 valueOf</span>
同理,alert要的是字符串不是原始值,其实是+bbb这个东西被调用了toString,而bbb被调用了valueOf
为了验证我们这样写
[javascript] view
plain copy
var a = {
i: 1,
valueOf: function () {
alert("你调用了a的valueOf函数");
return this.i;
},
toString: function () {
alert("你调用了a的toString函数");
return this.i;
}
};
var c = {
i: +a,
valueOf: function () {
alert("你调用了c的valueOf函数");
return this.i;
},
toString: function () {
alert("你调用了c的toString函数");
return this.i;
}
};
alert(c);
其中让c=+a,那么即可知道结果,果然如此,调用了a的valueOf和c的toString
第三个
[javascript] view
plain copy
alert(''+bbb); // 10 valueOf
同理,我们可以把上一段我写的程序里面的c:+a改成c:'’+a
第四个
[javascript] view
plain copy
alert(String(bbb)); // 10 toString
String这个强制转换其实在其内部是调用了传入参数的toString函数……
第五个
[javascript] view
plain copy
alert(Number(bbb)); // 10 valueOf
这个是有区别的,因为bbb的i属性是数值类型的,如果i为11111xxxxx这样的字符串,我们就可以看到调用了bbb的toString了
呐,代码例子
[javascript] view
plain copy
var c = {
i: "11111xxxx",
valueOf: function () {
alert("你调用了c的valueOf函数");
return this.i;
},
toString: function () {
alert("你调用了c的toString函数");
return this.i;
}
};
alert(c);
第六个
[javascript] view
plain copy
alert(bbb == '10'); // true valueOf
这个里面的判等的顺序是,获取原始值,然后判断两边的原始值是否相等,所以调用valueOf
第七个也就是最后一个
[javascript] view
plain copy
alert(bbb === '10'); // false
这个里面的判全等的第一个步骤是判断类型,因为类型都不一样了,所以后面什么都不会调用
讨论
另外,对于原文的这句话“ 在进行对象转换时(例如:alert(a)),将优先调用toString方法,如若没有重写toString将调用valueOf方法,如果两方法都不没有重写,但按Object的toString输出。”我不是很认同
原文例子
[javascript] view
plain copy
var aa = {
i: 10,
toString: function() {
console.log('toString');
return this.i;
}
}
alert(aa);// 10 toString
alert(+aa); // 10 toString
alert(''+aa); // 10 toString
alert(String(aa)); // 10 toString
alert(Number(aa)); // 10 toString
alert(aa == '10'); // true toString
我的观点有些不同,重写了的toString会被未重写的其prototype的valueOf隐式调用,而不是优先调用toString。虽然结果不同,但是其实没有优先级的变化。(但是我只能证明重写了的toString会被未重写的其prototype的valueOf隐式调用,却不能证明未重写和重写后的优先级变化读者如果完成了验证请教教我,我的js上周一才开始学。以下是例子)
[javascript] view
plain copy
var a = {
i: 1,
valueOf: function () {
alert("你调用了a的valueOf函数");
return Object.prototype.valueOf();
},
toString: function () {
alert("你调用了a的toString函数");
return this.i;
}
};
alert(+a);
alert(''+a);
结果的确调用了a的toString和a的valueOf,而我们可以很轻易的从最初的原文例子看到,这两个alert是没有调用国toString的,那么我们即可证明重写了的toString会被未重写的其prototype的valueOf隐式调用。
另一个原文的例子
[javascript] view
plain copy
var bb = {
i: 10,
valueOf: function() {
console.log('valueOf');
return this.i;
}
}
alert(bb);// [object Object]
alert(+bb); // 10 valueOf
alert(''+bb); // 10 valueOf
alert(String(bb)); // [object Object]
alert(Number(bb)); // 10 valueOf
alert(bb == '10'); // true valueOf
而valueOf被重写以后,这个bb的对象没有toString,自然就会调用其prototype的toString,而那个toString的内容必然是
[javascript] view
plain copy
function toString() {
return '[object Object]';
}
,所以其实这个验证并没有什么意义。无论重写哪个函数最终的优先级都没变。
总结
所以那篇的结论并不是最根本的问题,最根本的问题是到底操作对象所处的环境是什么样的。
如果要求的是原始值那么就会调用valueOf,如果要求的是字符串那么就会调用toString。
转自:http://blog.csdn.net/cct418/article/details/50889987
相关文章推荐
- js判断身份证号是否正确
- JSON
- javascript创建cookies无法保存至本地
- JavaScript作用域与作用域链
- 用Js的eval解析JSON中的注意点
- javascript 闭包
- JS操作JSON总结
- 小问题汇总——JS篇 -持续更新
- js中将字符串转换成json的三种方式
- JavaScript中的this(你不知道的JavaScript)
- 廖雪峰JS教程学习记录----iterable可迭代类型集合
- js正则表达式test方法的问题
- 深入剖析 JavaScript 的深复制
- jsp页面 date转化成string
- jsoup爬取百度瀑布流图片
- JSON和XML解析的理解
- js字符串作为一个对象类型
- 轻松搞定JSONP跨域请求
- Servlet —— 只有一个实例
- 简单的刮刮乐源码