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

彭老湿近期月报里提到了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的内部转换规则比想的要略复杂些,此处不展开。

啰啰嗦嗦说了一大通,现在还有两个问题存在疑惑

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

JS中令人发指的valueOf方法介绍相关推荐

  1. 一眼毁三观:JS中令人发指的valueOf方法

    剧透:文章末尾有两个小问题待解答,路过的兄弟请百忙之中抽空看下--- 彭老湿近期月报里提到了valueOf方法,兴致来了翻了下ECMA5里关于valueOf方法的介绍,如下: 15.2.4.4 Obj ...

  2. java有push方法么_[Java教程]js中push和join方法使用介绍

    [Java教程]js中push和join方法使用介绍 0 2013-10-09 07:00:17 push和join方法想必大家并不陌生吧,在本文将为大家详细介绍下js中的push和join方法的使用 ...

  3. JS中数组使用的方法

    JS中数组使用的方法 数组的介绍 JavaScript Array(数组):属于对象的一种 在句子中的作用就是使用一个单独的变量来存储一系列的值 数组的创建方法 1.字面量方式:var arr=[] ...

  4. js中关于Blob对象的介绍与使用

    js中关于Blob对象的介绍与使用 blob对象介绍 一个 Blob对象表示一个不可变的, 原始数据的类似文件对象.Blob表示的数据不一定是一个JavaScript原生格式 blob对象本质上是js ...

  5. vue 懒人_Vue.js 中的实用工具方法【推荐】

    收集日常开发中常用到的一些工具方法, 包含 vue 的公用过滤器.公用指令等 (PS: 懒人养成记) 公用自定义过滤器 import Vue from 'vue' import moment from ...

  6. js中match、replace方法中使用正则表达式

    为什么80%的码农都做不了架构师?>>>    js中match.replace方法中使用正则表达式 (2012-06-29 14:23:37) 转载▼ 标签: 字符串 飞雪 正则表 ...

  7. python使用get和post方法_python爬虫中get和post方法介绍以及cookie作用

    首先确定你要爬取的目标网站的表单提交方式,可以通过开发者工具看到.这里推荐使用chrome. 这里我用163邮箱为例 打开工具后再Network中,在Name选中想要了解的网站,右侧headers里的 ...

  8. js中数组常用的方法总结,包括ES6

    原文地址:js中数组常用的方法总结,包括ES6 1.push() 后增 push()方法可以向数组后添加一个新的元素,并返回新数组的长度. 末尾添加,返回长度,改变原数组 var a = [1,2,3 ...

  9. 罗克韦尔AB PLC RSLogix5000中定时器指令使用方法介绍

    罗克韦尔AB PLC RSLogix5000中定时器指令使用方法介绍 定时器指令用于控制基于时间的操作,属于输出指令. 定时器指令 定时器指令共有3个:  延时导通定时器 TON  延时断开定时器 ...

最新文章

  1. mysql5.5乱码问题_如何解决MySQL5.5的中文乱码问题
  2. 10-MySQL-Ubuntu-数据表中数据的查询(三)
  3. slowfast解读:用于计算机视觉视频理解的双模CNN
  4. python可抓取数据包括什么_Python对JS型数据抓取有什么特别好的方法吗,pythonjs型抓取,想写一个爬虫,但是需要抓...
  5. 设置datalist 中option的宽度_Flutter中http请求抓包的完美解决方案
  6. 软件工程导论个人项目 -- 中小学数学卷子自动生成程序
  7. Mabtyis无侵入式编程
  8. 阿里天猫、蚂蚁最全一百多道面试题以及阿里P8架构技能树分享(含答案解析)
  9. Distinct Characters Queries CodeForces - 1234D(线段树求区间字母种类数)
  10. 注解参数怎么使用变量_硅橡胶胶水有哪些特点?使用参数表现的怎么样?如何储存?...
  11. Human_height
  12. “智企云中享“,首届SAP中国云大会召开
  13. Struts1.x在MyEclipse中的环境搭建和配置
  14. WAMP安装curl扩展并发起https请求
  15. 培训loadrunner感受
  16. JS学习总结(4)——条件语句
  17. 酷q服务器未响应,酷Q [CQHTTP Python Async SDK] 入坑指南【已失效】
  18. 超级搜索术,提升解决问题的能力
  19. b2c常用的erp系统
  20. 基于WIKI中文语料·Word2Vec模型训练·Python

热门文章

  1. Java多线程之龟兔赛跑和抢票
  2. C++实现顺序串(完整代码)
  3. LeetCode 226翻转二叉树-简单
  4. 题目 2285: [蓝桥杯][2018年第九届真题]螺旋折线(数论+思维)
  5. python 进行一元线性回归并输出相关结果_Python实现一元线性回归实战
  6. 平衡二叉树AVL详解
  7. 2019-03-21-算法-进化(合并两个有序链表)
  8. 牛客练习赛71 F 红蓝图(kruskal重构树)
  9. P3292 [SCOI2016]幸运数字(树剖 + 线段树维护线性基)
  10. CF603D Ruminations on Ruminants(计算几何/Simson theorem)