关于toString()和valueOf()以及Object.prototype.toString.call()的结合理解
一、先说说String():
String()是全局函数,把对象的值转换为字符串。
语法:String(obj);
任何值(对象)都有String()方法,执行过程是这样的:首先,如果该对象上有toString()方法,则使用该方法(无参数),其次就是没有toString方法,那就是 null 返回 "null",undefined返回"undefined";
【个人理解:任何对象都有String()方法,因为这个全局函数;除了null和undefined,其他对象都有toString()方法】;
二、toString()
语法:obj.toString();
可以将除null和undefined外所有对象转为字符串。是所有内建的 JS 对象的成员,它的操作依赖于对象的类型。
1.将boolean类型的值转化为string类型:
console.log(true.toString());//"true"
console.log(false.toString());//"false"
2.将string类型按其字面量形式输出:
var str = "test123y";
console.log(str.toString());//"test123y"
3.将Object类型转化成string类型(JavaScript原生的Array类型、Date类型、RegExp类型以及Number、Boolean、String这些包装类型都是Object的子类型):
自定义Object类型(没有重新定义toString方法):
var obj = {name:"Tom", age:18};
console.log(obj.toString());//"[object Object]"此时调用的是从Object继承来的原始的toString()方法
【个人理解:既然都是object的子类型,为什么】
接下来的三个例子都是以重写的方式实现了toString()方法:
3.1Array类型:
var arr = ["tom",12,"rose",18];
console.log(arr.toString());//"tom,12,rose,18"
3.2RegExp类型
var patten = new RegExp("\\[hbc\\]at", "gi");
console.log(patten.toString());//"/\[hbc\]at/gi"
3.3Date类型
var date = new Date(2014,02,26);//注意这种格式创建的日期,其月份是3月
console.log(date.toString());//"Wed Mar 26 2014 00:00:00 GMT+0800"输出格式因浏览器不同而不同,此为firefox的输出格式;
3.4Number类型也是以重写的方式实现toString()方法的,请看以下例子:
3.4.1它可以接受一个整数参数,并将调用这个方法的数值转化成相应进制的字符串:
var num = 16;
console.log(num.toString(2));//10000 二进制
console.log(num.toString(8));//20 八进制
console.log(num.toString(16));//10 十六进制
console.log(num.toString(5));//31 虽然没有五进制,但是这样传参是可以被toString()方法接受的
3.4.2再看下面的代码:

console.log(1.toString());//这种写法会报错语法错误,但是下面的写法都是合法的;
console.log((1).toString());//"1"
console.log(typeof (1).toString());//string
console.log(1..toString());//"1"
console.log(typeof (1).toString());//string
console.log(1.2.toString());//"1"
console.log(typeof (1).toString());//string

var num = 0.000006;//小数点后面有5个“0”
console.log(num.toString());//"0.000006"
var num = 0.0000006;//小数点后面有6个“0”
console.log(num.toString());//"6e-7"
3.4.4浮点数整数部分的位数大于21时,输出时采用e表示法;
var num = 1234567890123456789012;
console.log(num.toString());//"1.2345678901234568e+21"
三、toString方法到底定义在何处?
先看一下代码:

var pro = Object.prototype;
var pr = pro.__proto__;//ie11之前版本不支持该属性
console.log(typeof pro);//"object"
console.log(String(pro));//"[object Object]"
console.log(pro.hasOwnProperty("toString"));//true
console.log(typeof pr);//"object"
console.log(String(pr));//"null"
console.log(pr.hasOwnProperty("toString"));//报错

由此可见,toString()定义在Object.prototype上;所以所有对象均可用toString()方法。
【个人理解:但为什么当对象是object的时候,输出的是'[object object]',而其他类型输出的却是类似本身的值?因为其他类型的对象引用的是重写后的toString()方法】
|
1
2
3
4
|
Object.prototype.toString( ) When the toString method is called, the following steps are taken:1. Get the [[Class]] property of this object.2. Compute a string value by concatenating the three strings “[object “, Result (1), and “]”.3. Return Result (2) |
上面的规范定义了 Object.prototype.toString 的行为:首先,取得对象的一个内部属性[[Class]],然后依据这个属性,返回一个类似于 "[object Array]" 的字符串作为结果([[]]用来表示语言内部用到的、外部不可直接访问的属性,称为 "内部属性")。利用这个方法,再配合 call,我们可以取得任何对象的内部属性 [[Class]],然后把类型检测转化为字符串比较,以达到我们的目的。还是先来看看在 ECMA 标准中 Array 的描述吧:
|
1
2
|
new Array([ item0[, item1 [,…]]])The [[Class]] property of the newly constructed object is set to “Array”. |
所以 Javascript 中判断数组的函数可以这样写:
|
1
2
3
|
function isArray(a) { Array.isArray ? Array.isArray(a) : Object.prototype.toString.call(a) === '[object Array]';} |
4.1.判断基本类型:
Object.prototype.toString.call(null);//”[object Null]”
Object.prototype.toString.call(undefined);//”[object Undefined]”
Object.prototype.toString.call(“abc”);//”[object String]”
Object.prototype.toString.call(123);//”[object Number]”
Object.prototype.toString.call(true);//”[object Boolean]”
4.2.判断原生引用类型:
4.2.1函数类型
Function fn(){console.log(“test”);}
Object.prototype.toString.call(fn);//”[object Function]”
4.2.2日期类型
var date = new Date();
Object.prototype.toString.call(date);//”[object Date]”
4.2.3数组类型
var arr = [1,2,3];
Object.prototype.toString.call(arr);//”[object Array]”
4.2.4正则表达式
var reg = /[hbc]at/gi;
Object.prototype.toString.call(arr);//”[object Array]”
4.2.5自定义类型
function Person(name, age) {
this.name = name;
this.age = age;
}
var person = new Person("Rose", 18);
Object.prototype.toString.call(arr); //”[object Object]”
很明显这种方法不能准确判断person是Person类的实例,而只能用instanceof 操作符来进行判断,如下所示:
console.log(person instanceof Person);//输出结果为true
4.3判断原生JSON对象:
var isNativeJSON = window.JSON && Object.prototype.toString.call(JSON);
console.log(isNativeJSON);//输出结果为”[object JSON]”说明JSON是原生的,否则不是;
注意:Object.prototype.toString()本身是允许被修改的,而我们目前所讨论的关于Object.prototype.toString()这个方法的应用都是假设toString()方法未被修改为前提的。
五、valueOf()和toString()
参考文章1:Javascript中valueOf与toString区别浅析
参开文章2:JavaScript的toString()和valueOf()区别到底是什么
参开文章3:valueOf()函数详解
关于toString()和valueOf()以及Object.prototype.toString.call()的结合理解的更多相关文章
- js精确判断数据类型为何用Object.prototype.toString.call()而不是Object.prototype.toString()
有何区别,为何一定要通过call. 我们知道call是用来改变函数作用域的,Object.prototype.toString.call在这儿也是用来改变作用域的. Object.prototype. ...
- Object.prototype.toString.call()进行类型判断
为什么类型判断用到Object.prototype.toString.call()进行类型判断,而不用typeof()呢? 然后翻了一下资料: Typeof 在使用 ]));/));));//[obj ...
- 为什么用Object.prototype.toString.call(obj)检测对象类型?
最近做了做一些js面试25 Essential JavaScript Interview Questions*,其中第一道是:使用typeof bar === "object"检测 ...
- 图形验证码知识点整理 Object.prototype.toString.call()等
使用typeof bar === "object"检测”bar”是否为对象有什么缺点?如何避免?这是一个十分常见的问题,用 typeof 是否能准确判断一个对象变量,答案是否定的, ...
- 【Object.prototype.toString.call()】---判断某个对象属于哪种内置类型------【巷子】
预热:目前我们知道区分对象类型的方式有三种 :type instanceof Object.prototype.toString.call. 那么这三种的区别是什么呢? type 在 Java ...
- Object.prototype.toString.call(arg)详解
经常能碰到Object.prototype.toString.call对参数类型进行判断,一开始只知道怎么使用,却不了解具体实现的原理,最近恶补了一下相关知识,写个笔记加强理解,有什么不对的请指教. ...
- Object.prototype.toString.call(obj)检测数据类型
typeof bar=='object' 不能确切判断数据是一个‘纯粹’的对象 Array null的结果都是object 比较好的方法是: Object.prototype.toString.cal ...
- 类型判断----小白讲解typeof,instanceof,Object.prototype.toString.call()
1.typeof只能判断基本类型数据, 例子: typeof 1 // "number" typeof '1' // "string" typeof true ...
- typeof 、Object.prototype.toString和 instanceof
数据类型 js 基本类型包括:Undefined symbol null string boolean number js 引用类型包括:object array Date RegExp typeo ...
随机推荐
- 基于vue上传base64图片,通过canvas压缩base64
其实和vue关系不大,和我们之前做上传压缩性质是一样的 当然下面的代码是没有处理ios横屏拍照的bug的 有兴趣的可以多搜一下 网上都有相应的解答 .. var that = this if (e. ...
- for-in语句和with语句、break和continue语句
for-in语句 for-in语句是一种精准迭代语句,可以用来枚举对象的属性,用以遍历一个对象的全部属性. for…in声明用于对数组或者对象的属性进行循环操作: for…in循环中的代码每执行一次, ...
- Serverless Kubernetes入门:对kubernetes做减法
背景 Kubernetes作为通用的容器编排系统,承载了广泛的应用和场景,包括CI/CD,数据计算,在线应用,AI等,然而由于其通用性和复杂性,管理一个kubernetes集群对于很多用户而言还是充满 ...
- 转:HTML5 History API 详解
从Ajax翻页的问题说起 请想象你正在看一个视频下面的评论,在翻到十几页的时候,你发现一个写得稍长,但非常有趣的评论.正当你想要停下滚轮细看的时候,手残按到了F5.然后,页面刷新了,评论又回到了第一页 ...
- Spring Cloud教程(十)自定义引导配置属性源
可以通过在org.springframework.cloud.bootstrap.BootstrapConfiguration键下添加条目/META-INF/spring.factories来训练引导 ...
- [CSP-S模拟测试]:ants(回滚莫队)
题目描述 然而贪玩的$dirty$又开始了他的第三个游戏. $dirty$抓来了$n$只蚂蚁,并且赋予每只蚂蚁不同的编号,编号从$1$到$n$.最开始,它们按某个顺序排成一列.现在$dirty$想要进 ...
- 9 关联管理器(RelatedManager)
知识预览: class RelatedManager class RelatedManager "关联管理器"是在一对多或者多对多的关联上下文中使用的管理器.它存在于下面两种情况: ...
- Catalan numbers
w https://en.wikipedia.org/wiki/Catalan_number 路径规划
- selinux 了解2
凡是对内核级, 如selinux的修改, 不只是对软件, 程序的修改, 那么修改之后都要重新启动. 针对windows下的截图, 像linux下的screenshot截图那样设置快捷键 shift+s ...
- 阶段1 语言基础+高级_1-3-Java语言高级_04-集合_06 Set集合_7_可变参数
打印出来是一个数组的地址 打印数组的长度 只要调用了add方法就会创建一各长度为0的数组 传一个10过去.就输出了数组的长度为1 传两个数字 注意事项: 特殊写法