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的使用场景,实际开发中尚未见到有兄弟用过
最后的最后:

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

(0)

相关推荐

  • js字符串的各种格式的转换 ToString,Format

    如果我们都计算出对的格式,然后再显示的话,显然浪费代码和效率,今天看见了许多ToString可以解决的格式,总结给大家,希望可以方便大家. 1.转换钱的格式,仅限int型,float型,double型 double d = 400; d.ToString("C"); //¥400.00 2.10进制数,仅限int型的数字 int i=400; i.ToString("D5"); // 00400 3.科学型数字,仅限int型,float型,double型 float

  • javascript中tostring()和valueof()的用法及两者的区别

    基本上,所有JS数据类型都拥有valueOf和toString这两个方法,null除外.它们俩解决javascript值运算与显示的问题. 1.用法如下: toString()方法:返回对象的字符串表示. 对象 操作 Array 将 Array 的元素转换为字符串.结果字符串由逗号分隔,且连接起来. Boolean 如果 Boolean 值是 true,则返回 "true".否则,返回 "false". Date 返回日期的文字表示法. Error 返回一个包含相关

  • 判断js中各种数据的类型方法之typeof与0bject.prototype.toString讲解

    1.typeof(param) 返回param的类型(string) 这种方法是JS中的定义的全局方法,也是编译者们最常用的方法,优点就是使用简单.好记,缺点是不能很好的判断object.null.array.regexp和自定义对象. 示例代码: 复制代码 代码如下: var str='str';var arr=['1','2'];var num=1;var bool=true;var obj={name:'test'};var nullObj=null;var undefinedObj=un

  • 非常好用的JsonToString 方法 简单实例

    非常好用的JsonToString方法Jsontostring代码 复制代码 代码如下: function JsonToString(o) {        var arr = [];     var fmt = function(s) {         if (typeof s == 'object' && s != null) return JsonToStr(s);         return /^(string|number)$/.test(typeof s) ? "

  • node.js中的buffer.toString方法使用说明

    方法说明: 将buffer对象转换成指定的字符编码的字符串. 语法: 复制代码 代码如下: buffer.toString([encoding], [start], [end]) 接收参数: encoding       转换成字符串后的字符编码,默认为 'utf8′ start                buffer 转换的起始位置,默认为 0 end                 buffer 转换的结束位置,默认为buffer长度 例子: 复制代码 代码如下: var b = new

  • 实例解析JS布尔对象的toString()方法和valueOf()方法

    toString() 方法 把布尔值转换为字符串,并返回结果. 实例 将布尔值转换为字符串: var bool = new Boolean(1); var myvar = bool.toString(); 输出结果: true 定义和用法 toString() 方法可把一个逻辑值转换为字符串,并返回结果. 注意:当需要把Boolean对象转换成字符串的情况JavaScript会自动调用此方法. 语法 boolean.toString() 返回值 "true" 或者 "fals

  • 重载toString实现JS HashMap分析

    不过请仔细对比一下,你会发现其中差别还是很大的.Java HashMap的key是Object类型,所以可以任何类型的参数,而JS的key只能是字符串或是数字. 你也许会说,obj={};map[obj]=1;这段代码传入了既不是数字也不是字符的key,但也没发生错误啊.那是因为解释器将obj对象通过内置的toString方法转换成"[object Object]"这段字符了,你可以用for each下map看看.而java之所以能够接受任何类型的key,是因为其Object实现了Ha

  • JavaScript中的object转换函数toString()与valueOf()介绍

    JavaScript中,object转换为boolean的操作非常简单:所有的object转换成boolean后均为true:即使是new Boolean(false)这样的object在转换为boolean后仍然为true. 复制代码 代码如下: var x = new Boolean(false); if(x){   console.log("x is true"); } 在将object转换为string或者number时,JavaScript会调用object的两个转换函数:t

  • Javascript中valueOf与toString区别浅析

    前言 基本上,所有JS数据类型都拥有这两个方法,null除外.它们俩解决javascript值运算与显示的问题,重写会加大它们调用的优化. 测试分析 先看一例: 复制代码 代码如下: var aaa = {  i: 10,  valueOf: function() { return this.i+30; },  toString: function() { return this.valueOf()+10; } } alert(aaa > 20); // true alert(+aaa); //

  • JavaScript中valueOf函数与toString方法深入理解

    JavaScript中valueOf函数方法是返回指定对象的原始值.使用方法: object.valueOf( )object是必选项参数是任意固有 JScript 对象. 每个JavaScript固有对象的 valueOf 方法定义不同. 对象 返回值 Array 数组的元素被转换为字符串,这些字符串由逗号分隔,连接在一起.其操作与 Array.toString 和 Array.join 方法相同. Boolean Boolean 值. Date 存储的时间是从 1970 年 1 月 1 日午

  • js资料toString 方法

    toString 方法 返回对象的字符串表示. objectname.toString([radix])参数 objectname  必选项.要得到字符串表示的对象.  radix  可选项.指定将数字值转换为字符串时的进制.  说明 toString 方法是所有内建的 JScript 对象的成员.它的操作依赖于对象的类型: 对象 操作  Array 将 Array 的元素转换为字符串.结果字符串由逗号分隔,且连接起来.  Boolean 如果 Boolean 值是 true,则返回 "true

随机推荐