JS中令人发指的valueOf方法

【菜科解读】
彭老湿近期月报里提到了valueOf方法,兴致来了翻了下ECMA5里关于valueOf方法的介绍,如下:
15.2.4.4 Object.prototype.valueOf ( )When thevalueOfmethod 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), thena. 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异常NumberNumber类型的对象,值等于objStringString类型的对象,值等于objBooleanBoolean类型的对象,值等于objObjectobj对象本身举几个具体的例子:
var num = 123;console.log(num.valueOf()); //输出:123console.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.valueOfString有,String.prototype.valueOfBoolean有,Boolean.prototype.valueOfObject-此处之外,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的内部转换规则比想的要略复杂些,此处不展开。
啰啰嗦嗦说了一大通,现在还有两个问题存在疑惑:
关于ToObject,当参数为Function对象时,返回对象作何处理似乎没见到规范里明确说明,当前仅靠实验猜测(也有可能是我没找到)
valueOf的使用场景,实际开发中尚未见到有兄弟用过
中,令人,发,指的,valueOf,方法,彭老湿,近期,昆仑山神秘事件经过
一位牧民冒险进入谷地寻马。
几天过去后,人没有出现,而马群却出现了。
后来他的尸体在一座小山上被发现。
衣服破碎,光着双脚,怒目圆睁,嘴巴张大,猎枪还握在手中,一副死不瞑目的样子。
让人不解的是,他的身上没有发现任何的伤痕或被袭击的痕迹。
到处都是倒毙的死牛和其他动物的骨骸,整个山坡充满了一种死亡的气息。
地质队认为这情况太过反常,为了寻求根源,他们迅速组织起来考察谷地。
考察后发现该地区的磁异常极为明显,而且分布范围很广,越深入谷地,磁异常值越高。
地质学家根据磁异常的现象推测在电磁效应作用下,云层中的电荷和谷地的磁场相互作用,产生电荷放电,电使这里成为多雷区,而雷往往以奔跑的动物作为袭击的对象。
科学无法解释的诡异现象上有闪电、下有暗河的昆仑山之谷与其地狱之门之称可谓是名副其实。
但对死亡之谷的秘密,地质学家的解释也只是触摸到一些皮毛,更艰巨的考察任务还在后头。
科学技术的发展让我们坚信,世界上没有永远的秘密,死亡谷之谜最终将为科学所解答。
海底人存在?世界各地发现的海底人踪迹
神秘蛤蟆人是不是海底人?1938年东欧波罗的海东岸的沙滩上,一群还海边游玩的人发现了一个不明生物,慢慢走进一瞧发现长相非常奇特,头圆圆的有点像蛤蟆,嘴宽又扁,胸部有点像鸡胸,之后蛤蟆人便发现了他们,以极快的速度跳进海里消失不见,因为事发突然没有留下任何踪迹,只在沙滩上留下一个巨大的类似蛤蟆的掌印。
幽灵潜艇是海底人所为吗?1973年在大西洋斯特里海湾一位船长正在驾驶自己的船航行着,之后他看到水下有幽灵般的潜艇正以极快的速度航行着,从他身边悄然而过。
时隔多年多艘军舰也遇到这个潜艇,军舰多次攻击无效,怪船浮出水面之后,军舰上设备全部失灵了,直达怪船消失才又恢复。
海底人存在吗?1.一种观点认为是海底人是存在的,因为人类最早的起源就是海洋,在现代人类的器官还有些地方保留着这方面的习惯,比如食盐、毛发较少、海生胎记等等,这些也是陆地上哺乳动物所没有的,所以就有人认为在进化过程中产生了分支,一部分上岸一部分还留在水中。
2.另外一种观点则认为海底人不是人类,菜科网,而是栖息在水中的外星人,对于外星人虽然我们知道的很少,但有很多人曾目击到UFO进入水中或者从水中突然出现,而这些生物的智慧似乎也远超人类。
其实到今天为止仍然有很多事情都没有办法去解释一些原因,人类所知甚少还是要不断探索才能发现新的东西,毕竟海洋占据了半个多地球,对于海洋人类算不上什么。