一眼毁三观: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的内部转换规则比想的要略复杂些,此处不展开。
啰啰嗦嗦说了一大通,现在还有两个问题存在疑惑:
- 关于ToObject,当参数为Function对象时,返回对象作何处理似乎没见到规范里明确说明,当前仅靠实验猜测(也有可能是我没找到)
- valueOf的使用场景,实际开发中尚未见到有兄弟用过
最后的最后:
文中示例如有错漏,请指出;如觉得文章对您有用,可点击“推荐” :)
一眼毁三观:JS中令人发指的valueOf方法相关推荐
- JS中令人发指的valueOf方法介绍
转载自 JS中令人发指的valueOf方法介绍 彭老湿近期月报里提到了valueOf方法,兴致来了翻了下ECMA5里关于valueOf方法的介绍,如下: 15.2.4.4 Object.protot ...
- JS中数组使用的方法
JS中数组使用的方法 数组的介绍 JavaScript Array(数组):属于对象的一种 在句子中的作用就是使用一个单独的变量来存储一系列的值 数组的创建方法 1.字面量方式:var arr=[] ...
- js中match、replace方法中使用正则表达式
为什么80%的码农都做不了架构师?>>> js中match.replace方法中使用正则表达式 (2012-06-29 14:23:37) 转载▼ 标签: 字符串 飞雪 正则表 ...
- vue 懒人_Vue.js 中的实用工具方法【推荐】
收集日常开发中常用到的一些工具方法, 包含 vue 的公用过滤器.公用指令等 (PS: 懒人养成记) 公用自定义过滤器 import Vue from 'vue' import moment from ...
- java有push方法么_[Java教程]js中push和join方法使用介绍
[Java教程]js中push和join方法使用介绍 0 2013-10-09 07:00:17 push和join方法想必大家并不陌生吧,在本文将为大家详细介绍下js中的push和join方法的使用 ...
- js中数组常用的方法总结,包括ES6
原文地址:js中数组常用的方法总结,包括ES6 1.push() 后增 push()方法可以向数组后添加一个新的元素,并返回新数组的长度. 末尾添加,返回长度,改变原数组 var a = [1,2,3 ...
- js中判断数据类型的方法
JS中判断数据类型的方法: 使用typeof操作符. 对一个值使用 typeof 操作符可能返回下列某个字符串,返回的类型都是字符串形式. (1) undefined:如果这个值未定义 (2) boo ...
- JS中 new Date() 各方法的用法
JS中 new Date() 各方法的用法 1.new Date() 参数篇 a.返回类型为国标时间, b.无参数时可以直接返回输出时的时间, c.有参数时则返回对应时间的国标时间, d.日期中间的符 ...
- java和js中替换字符串的方法
//java中字符串的替换方法: String a = "吴林飞-1a_,唐姐-2,周帅-3"; String f = a.replaceFirst("-", ...
最新文章
- 测试工程师工作流程概论
- activiti源码编译
- 数据挖掘系列(1)关联规则挖掘基本概念与Aprior算法
- 国内物联网平台初探(七) ——Ablecloud物联网自助开发和大数据云平台
- html div圆滑效果,美化网页div -让边框拥有阴影,边角变得圆滑
- 公共语言运行库中的程序集-04强命名的程序集
- chrome插件分享
- 力扣有没有java_【Java】一篇文章带你玩转用Java刷力扣
- 微机原理换行代码_微机原理
- 【CF 670C】Cinema
- 某生鲜平台面试题:如何保证库存在高并发的场景下是安全的?
- zookeeper使用问题汇总
- 计算机软件毕业论文教师指导记录,【毕业论文指导教师指导记录】论文指导记录16篇...
- oracle语句中,Oracle 语句中“||”代表什么啊?
- Seaweedfs 详细说明
- 邮政出面打假?中国邮政是否考虑搭建其品牌官网?
- 知云文献翻译打不开_沙拉查词—— 划线翻译的一股清流
- 关于md文件插入视频链接的方法。(亲测可用)
- 算一串数字的entropy_什么是熵的计算机科学定义?
- 网络对抗 Exp4 恶意代码分析 20154311 王卓然
热门文章
- 【网寻】mui - 点击事件
- 【以太坊】ubuntu安装以太坊ethereum的测试网络ropsten-net以及雷电网络raiden-network环境...
- es6 初步深入学习
- Schmid Telecom选择StoreAge SVM实现数据镜像保护
- 计算机网络的硬件连接图,路由器设置图和网络电缆连接图_计算机硬件和网络_IT /计算机_数据...
- jQuery HTML 添加和删除元素
- .net后台获取html控件值的2种方法
- mvc与三层结构终极区别
- 监听ListView滚动到最底部
- 后台开发实用书籍--后台开发:核心技术与应用实践