彭老湿近期月报里提到了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中toString和valueOf方法的区别

    toString 方法 返回对象的字符串表示形式. 语法:objectname.toString([radix]) objectname 必需.要为其搜索字符串表示形式的对象. radix 可选.为将 ...

  2. js 中concat()和slice()方法介绍

    1.concat() concat() 方法用于连接两个或多个数组. 该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本. <script type="text/javascr ...

  3. JS中部分 Array 对象方法介绍

    1.concat() concat() 方法用于连接两个或多个数组.该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本 <script type="text/javascrip ...

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

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

  5. node.js中的url.parse方法使用说明

    node.js中的url.parse方法使用说明:https://blog.csdn.net/swimming_in_it_/article/details/77439975 版权声明:本文为博主原创 ...

  6. js中push和join方法使用介绍

    push和join方法想必大家并不陌生吧,在本文将为大家详细介绍下js中的push和join方法的使用.代码: <script type="text/javascript"& ...

  7. JS中常用的Math方法

    1.min()和max()方法 Math.min()用于确定一组数值中的最小值.Math.max()用于确定一组数值中的最大值. alert(Math.min(2,4,3,6,3,8,0,1,3)); ...

  8. JS中 call() 与apply 方法

    1.方法定义 call方法: 语法:call([thisObj[,arg1[, arg2[,   [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象. 说明: call ...

  9. JS中定义类的方法

    JS中定义类的方式有很多种: 1.工厂方式    function Car(){     var ocar = new Object;     ocar.color = "blue" ...

随机推荐

  1. JAVA类与对象(二)----类定义基础

    类是组成java程序的基本要素,是java中的一种重要的复合数据类型.它封装了一类对象的状态和方法,是这一类对象的原型.一个类的实现包括两个部分:类声明和类体,基本格式: class <clas ...

  2. JAVA SSH 框架介绍

    SSH 为 struts+spring+hibernate 的一个集成框架,是目前较流行的一种JAVA Web应用程序开源框架. Struts Struts是一个基于Sun J2EE平台的MVC框架, ...

  3. WPF 多线程处理(5)

    WPF 多线程处理(1) WPF 多线程处理(2) WPF 多线程处理(3) WPF 多线程处理(4) WPF 多线程处理(5) WPF 多线程处理(6) 项目的目录: 以下是FileStroage的 ...

  4. Careercup - Facebook面试题 - 4907555595747328

    2014-05-02 07:49 题目链接 原题: Given a set of n points (coordinate in 2d plane) within a rectangular spac ...

  5. 循序渐进Java Socket网络编程(多客户端、信息共享、文件传输)

    目录[-] 一.TCP/IP协议 二.TCP与UDP 三.Socket是什么 四.Java中的Socket 五.基本的Client/Server程序 六.多客户端连接服务器 七.信息共享 八.文件传输 ...

  6. iOS$299企业账号In House ipa发布流程

    1.在Mac系统中进入“钥匙串访问”,选择“钥匙串访问”-“证书助理”-“从证书颁发机构请求证书”. 填写前两项,并保存在本地. 2.登录https://developer.apple.com,进入i ...

  7. list 去掉重复的值

    去除List列表中重复值(3种解决方法)public static void main(String[] args) { String[] ar = { "dd", "c ...

  8. SQL中的事物【转】

    来源于:http://www.cnblogs.com/zhuifengnianshao/archive/2010/11/24/1886939.html 事务(Transaction)是并发控制的单位, ...

  9. 1829 A Bug's Life

    A Bug's Life Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  10. [转]Ubuntu 12.04 安装屏保

    From:http://www.howtogeek.com/114027/how-to-add-screensavers-to-ubuntu-12.04/ How to Add Screensaver ...