JS中令人发指的valueOf方法介绍


Posted in Javascript onFebruary 22, 2013

彭老湿近期月报里提到了valueOf方法,兴致来了翻了下ECMA5里关于valueOf方法的介绍,如下:

15.2.4.4 Object.prototype.valueOf ( )
When the valueOf method is called, the following steps are taken:
1. Let O be the result of calling ToObject passing the this value as the argument.
2. If O is the result of calling the Object constructor with a host object (15.2.2.1), then
a. Return either O or another value such as the host object originally passed to the constructor. The specific result that is returned is implementation-defined.
3. Return O.
规范里面的对于valueOf的解释很短,大致为:调用ToObject方法(一个抽象方法,后面会讲到),并将this的值作为参数传入。

针对调用ToObject时传入的不同参数(this),返回值分别如下:

1、this为宿主对象时,返回值取决于浏览器的实现,即不同浏览器的返回可能不同(关于宿主对象,可参考http://www.w3school.com.cn/js/pro_js_object_types.asp)
2、this不是宿主对象,则返回ToObject(this)的值 

参数类型 返回结果
Undefined 抛出TypeError异常
Null 抛出TypeError异常
Number 创建一个Number对象,它内部的初始值为传入的参数值
String 创建一个String对象,它内部的初始值为传入的参数值
Boolean 创建一个Boolean对象,它内部的初始值为传入的参数值
Object 返回传入的参数(无转换)

根据Object.prototype.valueOf的定义,以及抽象方法ToObject的描述,可得下表 
obj类型 Object.prototype.valueOf.call(obj)返回结果
Undefined 抛出TypeError异常
Null 抛出TypeError异常
Number Number类型的对象,值等于obj
String String类型的对象,值等于obj
Boolean Boolean类型的对象,值等于obj
Object obj对象本身

举几个具体的例子:
var num = 123; 
console.log(num.valueOf()); //输出:123 
console.log(num.valueOf()); //输出:'number' var unde = undefined; 
console.log(Object.prototype.valueOf.call(unde)); //输出:'TypeError: Cannot convert null to object' 
var obj = {name:'casper'}; 
var linkObj = obj.valueOf(); 
linkObj.name = 'change'; 
console.log(linkObj.name); //输出:'change' ...说明obj.valueOf()返回的是对象自身

实际上,上面没有提到Array、Function对象,根据下面代码可以猜想,当Object.prototype.valueOf调用时,参数为Array、Function类型的对象时,返回的结果也为对象自身:
var arr = [1, 2 ,3]; 
var linkArr = arr.valueOf(); 
linkArr[0] = ['casper']; 
console.log(linkArr); //输出:['casper', 2, 3] var foo = function(){ return 1; }; 
var linkFoo = foo.valueOf(); 
linkFoo.test = 'casper'; 
console.log(linkFoo.test); //输出:'casper'

看完上面的描述,是不是有种恍然大悟的感觉?如果是的话,恭喜你,可能你跟我一样其实还没完全理解透彻。

简单举个例子,当调用Object.prototype.valueOf的对象为数值类型时,假设该对象是名称为num,num很有可能通过下面两种方式声明:

var num = 123; //通过对象字面量声明console.log(typeof num); //输出:'number' 
var num = new Number(123); //通过构造方法声明console.log(typeof num); //输出:'object'

更多变态声明方式,可参见《JS中不为人知的五种声明Number的方式》

关于返回值的说明,ECMA5里面原文如下

Create a new Number object whose [[PrimitiveValue]] internal property is set to the value of the argument. See 15.7 for a description of Number objects.
按照这段文字的说明,似乎num.valueOf()返回的应该是个Number对象(非字面量声明的那种),但实际上:

var num = 123; 
var tmp = num.valueOf(); 
console.log(typeof tmp); //输出: 'number'

这是怎么回事呢?于是又仔细翻看了下,似乎有些接近真相了:
5.7.4.4 Number.prototype.valueOf ( )

Returns this Number value.

The valueOf function is not generic; it throws a TypeError exception if its this value is not a Number or a Number object. Therefore, it cannot be transferred to other kinds of objects for use as a method.
原来Number有属于自身的原型valueOf方法,不是直接从Object.prototype上继承下来,类似的,Boolean、String也有自己的原型valueOf方法,归纳如下:

类型 是否有属于自己的原型valueOf方法
Undefined
Null
Number 有,Number.prototype.valueOf
String 有,String.prototype.valueOf
Boolean 有,Boolean.prototype.valueOf
Object -
此处之外,Array、Function并没有自己的原型valueOf方法,见规范说明:

NOTE The Array prototype object does not have a valueOf property of its own; however, it inherits the valueOf property from the standard built-in Object prototype Object.
The Function prototype object does not have a valueOf property of its own; however, it inherits the valueOf property from the Object prototype Object.
补充说明:Number.prototype.valueOf的内部转换规则比想的要略复杂些,此处不展开。

???锣滤盗艘淮笸ǎ?衷诨褂辛礁鑫侍獯嬖谝苫?/STRONG>:

1.关于ToObject,当参数为Function对象时,返回对象作何处理似乎没见到规范里明确说明,当前仅靠实验猜测(也有可能是我没找到)
2.valueOf的使用场景,实际开发中尚未见到有兄弟用过
最后的最后:

文中示例如有错漏,请指出;如觉得文章对您有用,可点击“推荐” :)

Javascript 相关文章推荐
cloudgamer出品ImageZoom 图片放大效果
Apr 01 Javascript
拖动布局之保存布局页面cookies篇
Oct 29 Javascript
Javascript变量作用域详解
Dec 06 Javascript
js中判断对象是否为空的三种实现方法
Dec 23 Javascript
jQuery插件Elastislide实现响应式的焦点图无缝滚动切换特效
Apr 12 Javascript
基于jquery实现鼠标左右拖动滑块滑动附源码下载
Dec 23 Javascript
jQuery实现导航滚动到指定内容效果完整实例【附demo源码下载】
Sep 20 Javascript
JavaScript SHA-256加密算法详细代码
Oct 06 Javascript
js编写选项卡效果
May 23 Javascript
vue新vue-cli3环境配置和模拟json数据的实例
Sep 19 Javascript
微信小程序实现简单表格
Feb 14 Javascript
jquery实现广告上下滚动效果
Mar 04 jQuery
网页右键ie不支持event.preventDefault和event.returnValue (需要加window)
Feb 22 #Javascript
javascript 日期时间 转换的方法
Feb 21 #Javascript
JS关键字变色实现思路及代码
Feb 21 #Javascript
js数组Array sort方法使用深入分析
Feb 21 #Javascript
js自定义方法通过隐藏iframe实现文件下载
Feb 21 #Javascript
jquery实现每个数字上都带进度条的幻灯片
Feb 20 #Javascript
javascript通过class来获取元素实现代码
Feb 20 #Javascript
You might like
让你的WINDOWS同时支持MYSQL4,MYSQL4.1,MYSQL5X
2006/12/06 PHP
简单实用的网站PHP缓存类实例
2014/07/18 PHP
php文件操作小结(删除指定文件/获取文件夹下的文件名/读取文件夹下图片名)
2016/05/09 PHP
thinkPHP5.0框架简单配置作用域的方法
2017/03/17 PHP
微信推送功能实现方式图文详解
2019/07/12 PHP
laravel 框架结合关联查询 when()用法分析
2019/11/22 PHP
静态页面的值传递(三部曲)
2006/09/25 Javascript
清除div下面的所有标签的方法
2014/02/17 Javascript
jquery如何把数组变为字符串传到服务端并处理
2014/04/30 Javascript
JavaScript处理解析JSON数据过程详解
2015/09/11 Javascript
angularjs自定义ng-model标签的属性
2016/01/21 Javascript
jQuery fadeOut 异步实例代码详解
2016/08/18 Javascript
浅谈js对象的创建和对6种继承模式的理解和遐想
2016/10/16 Javascript
NodeJS基础API搭建服务器详细过程记录
2017/04/01 NodeJs
Nodejs中怎么实现函数的串行执行
2019/03/02 NodeJs
利用Python演示数型数据结构的教程
2015/04/03 Python
使用python检测主机存活端口及检查存活主机
2015/10/12 Python
Python输出汉字字库及将文字转换为图片的方法
2016/06/04 Python
Python实现发送QQ邮件的封装
2017/07/14 Python
Python字符串格式化常用手段及注意事项
2020/06/17 Python
PyTorch实现重写/改写Dataset并载入Dataloader
2020/07/14 Python
Selenium及python实现滚动操作多种方法
2020/07/21 Python
基于Python-turtle库绘制路飞的草帽骷髅旗、美国队长的盾牌、高达的源码
2021/02/18 Python
CSS3制作炫酷带方向感应的鼠标滑过图片3D动画
2016/03/16 HTML / CSS
英国领先的奢侈品零售商之一:CRUISE
2016/12/02 全球购物
中国电视购物:快乐购
2017/02/04 全球购物
PHP如何与mysql建立链接
2013/05/05 面试题
.net面试题
2016/09/17 面试题
房屋租赁协议书范本
2014/04/10 职场文书
党员承诺书范文
2014/05/19 职场文书
社会公德演讲稿
2014/05/20 职场文书
个人四风问题对照检查材料
2014/10/01 职场文书
2015年节能降耗工作总结
2015/05/22 职场文书
幼儿园开学温馨提示
2015/07/15 职场文书
三年级作文之趣事作文
2019/11/04 职场文书
flex弹性布局详解
2022/03/20 HTML / CSS