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

转载自  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异常
NumberNumber类型的对象,值等于obj
StringString类型的对象,值等于obj
BooleanBoolean类型的对象,值等于obj
Objectobj对象本身


举几个具体的例子:

代码如下:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/323194.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P3203-[HNOI2010]弹飞绵羊【分块】

正题 评测记录:https://www.luogu.org/recordnew/lists?uid52918&pidP3203 题目大意 nnn个装置。到第iii个装置会被往前弹aia_iai​个。 两种操作 修改aia_iai​和询问从iii出发要多少次弹射可以弹出去。 解题思路 分块。对于每个点,维护要多少步弹出该块和弹…

Lyft的TypeScript实践

来自Lyft的前端工程师Mohsen Azimi介绍了Lyft向TypeScript转型的过程,说明JavaScript类型系统的重要性、为什么Lyft选择TypeScript以及他们的一些实践经验。以下内容翻译自作者的博客,查看原文TypeScript at Lyft。 在我刚刚成为JavaScript开发者的时候&…

【Python】Conda的安装

挖个坑,以后自己慢慢填:下载conda后无法使用 conda优势:conda将几乎所有的工具、第三方包都当做package对待,甚至包括python和conda自身!因此,conda打破了包管理与环境管理的约束,能非常方便地…

C++描述杭电OJ 2014. 青年歌手大奖赛_评委会打分 ||

C描述杭电OJ 2014. 青年歌手大奖赛_评委会打分 || Problem Description 青年歌手大奖赛中,评委会给参赛选手打分。选手得分规则为去掉一个最高分和一个最低分,然后计算平均得分,请编程输出某选手的得分。 Input 输入数据有多组&#xff0c…

Java AIO 编程

转载自 java aio 编程 Java NIO (JSR 51)定义了Java new I/O API,提案2000年提出,2002年正式发布。 JDK 1.4起包含了相应的API实现。 JAVA NIO2 (JSR 203)定义了更多的 New I/O APIs, 提案2003提出,直到2011年才发布, 最终在JDK …

P1494-[国家集训队]小Z的袜子【分块优化莫队】

正题 评测记录:https://www.luogu.org/recordnew/lists?uid52918&pidP1494 题目大意 区间任意取两个数,求取到相同的数的概率。 解题思路 假设一个区间有x个y,那么两个都取到y的方案数是x∗(x−1)x*(x-1)x∗(x−1),那么取到相同总共方…

通过Swashbukle给DotNet Core Web API 增加自动文档功能

DotNet Core Web API给开发者提供了一个很好的框架来开发Restful的API。那么这些API接口该如何管理起来呢?Swagger是一个很好的选择,Swagger不需要开发者额外去维护接口文档,只要开发者的接口遵循Restful的规范,Swagger就会根据AP…

【Python】urllib爬取动漫图片

首先附上需要爬取图片的网站&#xff0c;应该算是个冷门网站&#xff0c;够练手用的了&#xff0c;我的博客图片大部分来自于这里 二次元图片网站 筛选src里的数据 用par r’<img src"[^"].jpg">可以筛选出带有里面的内容 htmldasdas <img src"…

P4137-Rmq Problem/mex【莫队,分块】

正题 评测记录:https://www.luogu.org/recordnew/lists?uid52918&pidP4137 题目大意 求区间mex。 解题思路 开始发现aia_iai​很大&#xff0c;开不了桶。但是转念一想&#xff0c;如果ans>n1ans>n1ans>n1仅当前n1个都有&#xff0c;可是最多只有n个&#xff…

【Python】字符串和变量拼接的写法

我的需求是改变url地址的后缀&#xff0c;其他不改&#xff0c;所以直接for循环&#xff0c;变换数字就行 也就是 字符串变量字符串 想着改变后缀就能批量爬图。但是原本的想法是错误的 for num in range(2,8):url"http://www.win4000.com/wallpaper_detail_160877_"…

Java面试,如何在短时间内做突击

转载自 Java面试&#xff0c;如何在短时间内做突击 面试技术文 Java岗 面试考点精讲&#xff08;基础篇01期&#xff09; Java岗 面试考点精讲&#xff08;基础篇02期&#xff09; Java岗 面试考点精讲&#xff08;网络篇03期&#xff09; Java 面试中遇到的坑 Java面试中…

【学校作业】学生数据打印

数据结构课程布置了一门c语言的结构体作业 要求&#xff1a; 五个学生&#xff0c;数据包括学号&#xff0c;姓名&#xff0c;3门课的成绩&#xff0c;从键盘输入5个学生的数据。打印出3门课总平均成绩&#xff0c;以及最高分 强迫症患者表示打印出的数据必须美观&#xff0c; …

P4879-ycz的妹子【分块】

正题 评测记录:https://www.luogu.org/recordnew/lists?uid52918&pidP4879 题目大意 有若干种操作 Cxy:ax−yC\ x\ y:a_x-yC x y:ax​−yIxy:I\ x\ y:I x y:加一个(原本有的话就改变)axya_xyax​yQ:Q:Q:询问所以数的和Dx:D\ x:D x:删除第xxx个(有的才算)数。 解题思路 …

Entity Framework Core 2.0 使用入门

一.前言 Entity Framework&#xff08;后面简称EF&#xff09;作为微软家的ORM&#xff0c;自然而然从.NET Framework延续到了.NET Core。以前我也嫌弃EF太重而不去使用它&#xff0c;但是EF Core&#xff08;Entity Framework Core&#xff09;已经做了很多性能优化&#xff0…

JavaFX中WebView的java与JS代码互相调用

java代码 package main;import javafx.application.Application; import javafx.beans.value.ObservableValue; import javafx.concurrent.Worker; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.VBox; import javafx.scene.w…

【Python】有效资源爬取并集

由于爬虫代码都不多&#xff0c; 所以我决定在这篇博文上更新所有我觉得比较实用的python代码 方便以后自己调用 环境:python3.7 百度图片爬虫 二次元图片爬取 唐三小说爬取 文件格式命名 百度图片爬虫 百度图片网站 import re import requests from urllib import err…

[编程入门]带参数宏定义练习:定义一个带参的宏,使两个参数的值互换,并写出程序,输入两个数作为使用宏时的实参。输出已交换后的两个值。

#include<bits/stdc.h> #define fun(a,b) ta;ab;bt; using namespace std;int main() {int a,b,t;cin>>a>>b;fun(a,b);cout<<a<<" "<<b;return 0; }

Jexus~docker与它产生了暖味

前段时间写了很多docker for .net core的文章&#xff0c;用来快速部署微服务相当给力&#xff0c;而尝到了香头的我们希望把.net frameworks的程序也使用docker来部署一下&#xff0c;那么接下来我就结果一下&#xff0c;在linux,docker上运行和部署.net frameworks应用程序的…

P3870-[TJOI2009]开关【分块】

正题 解题思路:https://www.luogu.org/recordnew/lists?uid52918&pidP3870 题目大意 n个灯&#xff0c;操作[0,l,r][0,l,r][0,l,r]表示l∼rl\sim rl∼r的灯取反&#xff0c;操作[1,l,r][1,l,r][1,l,r]表示询问l∼rl\sim rl∼r之间有多少灯亮着。 解题思路 分块&#xf…

Linux运维常用检查网络工具

一、Ping ping可以检查网络是否连通&#xff0c;可以很好地帮助我们分析和判定网络故障。 ping ip 二、Telnet telnet通常用来查看某个端口是否可访问。 telnet ip port 三、Curl curl是一个利用URL语法在命令行下工作的文件传输工具&#xff0c;1997年首次发行。它支持…