toString & valueOf
来源:互联网 发布:fedora dnf和yum 编辑:程序博客网 时间:2024/05/01 13:42
这几天在看《深入理解ES6》,这本书的作者是Nicholas C. Zakas,也就是我最爱的《高程》作者~~不过还是得把目标中的文章部分写一下。
今天我要讲的是toString()和valueOf()。
toString()
相比于toString(),我更愿意叫它实例对象.proto.toString()。
顾名思义:toString()就是将任何数据类型转换为字符串类型(Null、undefined以及[object Object]除外)。
那么number类型和boolean也会转换吗?答案是当然~
let obj = { "name" : "suoz", "age" : 20};let num = 123;let arr = ["1","red",3];let flag = true;console.log(obj.toString()); //[object Object]console.log(typeof(num.toString())); //stringconsole.log(typeof(arr.toString())); //stringconsole.log(typeof(flag.toString())); //string
我觉得这里会疑惑两点
第一点:为什么number和boolean类型的变量可以调用toString()方法。
在另外一篇文章中我说过,number、boolean、string类型可以是属于一种特殊的引用类型(基本包装类型)。
let num = 123;num.toString(); //读取模式
当创建其中一种类型的变量时,在访问该变量的时候(”读取”模式),后台会自动帮助我们完成以下操作。
let num = new Number(123); //创建一个Number类型的对象num.toString(); //使用该对象的方法num = null; //使用后 立即将该对象销毁
这就在不知不觉中,用户调用了number类型的方法,但是没有任何感觉。
第二点:Object类型调用toString()方法返回的是[object Object]??
其实这就为我们下面的Object.prototype.toString()的介绍作了铺垫。
这里先粗略解释,因为使用toString()方法调用的是该对象[[proto]]指向的原型对象内部的toString(),而不是Object.prototype.toString(),但由于Object类型的对象[[proto]]指向的原型对象还是Object.prototype.toString(),所以它调用了这个方法。
let obj = {"name":"suoz"};console.log(obj.toString()); //[object Object]console.log(obj.__proto__ === Object.prototype); //trueObject.prototype.toString = function(){ console.log("hello world!");};console.log(obj.toString()); //hello world!
其实它内部实现机制是这样的:
实例对象.__proto__.toString = function(){ var str = ""; for(var i=0; i<this.length-1; i++) { str += this[i] + ","; } str += this[this.length-1]; return str; };
Object.prototype.toString()
通常我们可以使用它来进行引用数据类型的判断。
let num = new Number(123);let str = new String("hello");let flag = new Boolean(true);let arr = ["red","pink"];let obj = {"name":"suoz"};let a = null;let b = undefined;console.log(Object.prototype.toString.call(num)); //[object Number]console.log(Object.prototype.toString.call(str)); //[Object String]console.log(Object.prototype.toString.call(flag)); //[Object Boolean]console.log(Object.prototype.toString.call(arr)); //[Object Array]console.log(Object.prototype.toString.call(obj)); //[Object Object]console.log(Object.prototype.toString.call(a)); //[Object NULL]console.log(Object.prototype.toString.call(b)); //[Object Undefined]
每次创建一个对象,都会为该对象的原型对象内部增加toString方法,所以直接调用对象的toString方法时,根据原型链机制,会调用对象[[proto]]指向的原型对象内部toString,而不是Object.prototype内部的toString
let arr = ["red","color"];console.log(arr.toString()); //"red,color"console.log(Object.prototype.toString.call(arr)); //[object Array]console.log(arr.__proto__.hasOwnProperty("toString")); //trueconsole.log(Object.prototype.hasOwnProperty("toString")); //truearr.__proto__.toString = function(){ console.log("hello world!");};console.log(arr.toString()); //hello world!arr.__proto__.toString = null;console.log(arr.toString()); //[object Array]
valueOf()
第一种情况:基本数据类型
let num = 123;let str = "hello";let flag = true;
console.log(num.__proto__.hasOwnProperty("valueOf")); //trueconsole.log(num.valueOf()); //123Object.prototype.valueOf = function(){ console.log("Object.prototype.valueOf");};console.log(num.valueOf()); //123num.__proto__.toString = function(){ console.log("toString");};console.log(num.valueOf()); //123num.__proto__valueOf = function(){ console.log("num.__proto__.valueOf");};console.log(num.valueOf()); //num.__proto__.valueOf
创建一个基本数据类型的值时,对象[[proto]]指向原型对象内部有valueOf,所以会覆盖Object.prototype.valueOf方法。(并且内部的valueOf和Object.prototype.valueOf方法内部实现机制不一样,前者不会调用toString,而后者会调用原型对象内部的toString方法,下面会仔细讲解)
第二种情况分析在下面。
Object.prototype.valueOf()
定义:将对象转换为原始值(number、string、boolean类型)。你很少需要自己调用此函数,当遇到一种需要转换为原始值的情况时,系统会自动调用。
默认情况下, valueOf() 会被每个对象Object继承。每一个内置对象都会覆盖这个方法为了返回一个合理的值,如果对象没有原始值,valueOf() 就会返回对象自身。
第二种情况:引用数据类型
let obj = {"name":"suoz"};let arr = ["red","pink"];
console.log(arr.__proto__.hasOwnProperty("valueOf")); //falseconsole.log(Object.prototype.hasOwnproperty("valueOf")); //trueconsole.log(arr.__proto__.hasOwnProperty("toString")); //trueconsole.log(arr.valueOf()); //["red","color"]Object.prototype.valueOf = function(){ console.log("valueof");};console.log(arr.valueOf()); //valueOf、undefined
验证创建一个引用类型对象(除了Object类型),该实例对象[[proto]]指向的原型对象内部没有valueOf方法,只有toString方法。
Object.prototype.toString = function(){ console.log("Object toString");};console.log(arr.valueOf()); //["red","pink"]console.log(arr == "red,pink"); //truearr.__proto__.toString = function(){ console.log("__proto__ toString"); return "red,pink";};console.log(arr.valueOf()); //__proto__ toString、["red","pink"]console.log(arr == "red,pink"); //__proto__ toString、true
验证了Object类型和Array类型都是用的Object.prototype.valueOf(),而Object.prototype.valueOf内部实现机制中包括调用了实例对象原型对象的toString方法
这里我疑惑的是为什么”==”返回”red,pink”,而调用valueOf()返回的是[“red”,”pink”],它们不都是直接使用了Object.prototype.valueOf吗(并且该方法内部又调用了实例对象[[proto]]指向原型对象的toString方法吗)?
Object.prototype.valueOf = function(){ console.log("Object valueOf");};console.log(arr.valueOf()); //Object valueOf、undefinedconsole.log(arr == "red,pink"); //Object valueOf、false
我觉得这里疑惑点还是得考了解一下Object.prototype.valueOf内部实现机制(源代码)去解决。(个人认为可以暂时性按下面的代码理解内部,后续补充)
arr.__proto__.toString = function(){ return "red,pink";};Object.prototype.valueOf = function(){ var str = arr.__proto__.toString.call(this); if(//如果这里是"=="){ //return str; //"red,pink" }else if(//如果这里是直接调用valueOf){ //return this; //返回对象本身 ["red","pink"] }};
什么时候调用toString或valueOf(后续补充)
总结:
- 使用Object.prototype.toString().call()方法,可以判断任何数据类型。
- 创建一个对象,该对象内部的方法toString会覆盖Object.prototype.toString方法,因此直接调用toString的时候,根据原型链搜索属性机制,会搜索该对象[[proto]]指向的原型对象内部的toString方法。
- [[proto]]指向的原型对象内部的toString方法 与 Object.prototype.toString方法内部实现机制是不一样的。前者是返回字符串类型值,后者是返回数据的类型[object XXX]
- 对于基本数据类型来说,创建一个变量或者对象,内部都会有valueOf方法覆盖Object.prototoye.valueOf方法。
- 对于引用类型来说,创建一个对象,内部不会覆盖方法,所以调用valueOf还是使用的Object.prototype.valueOf方法。
- 对于基本类型来说,覆盖的valueOf方法不会隐式调用toString方法
- 对于引用类型来说,Object.prototype.valueOf方法内部会隐式调用toString方法。
- valueOf && toString
- toString & valueOf
- java.toString() ,(String),valueOf
- java.toString() ,(String),valueOf
- java.toString() ,(String),valueOf
- parse(),ValueOf(),toString()
- toString与String.valueOf()
- String.valueOf和toString
- toString() ,String,String.valueOf
- .toString和String.valueOf()
- js的 valueOf & toString
- toString 和String.valueOf
- toString()和valueOf()
- valueOf() 、parseInt() 、toString()
- toString()和valueOf()
- JS中 toString() & valueOf()
- 关于String.valueOf()和toString
- [转载]java.toString() ,(String),valueOf
- python模块大全
- Spark2.x技术内幕
- 机器学习算法原理与编程实践
- 欢迎使用CSDN-markdown编辑器
- Ext4 Howto
- toString & valueOf
- Canny边缘检测原理与C++实现(1)原理部分
- NOIP普及组复赛培训安排
- haproxy+nginx+tomcat+memcache实现动静分离、会话同步集群
- 面试题64. 数据流中的中位数
- JavaScript中8个常见的陷阱
- Redis Sentinel安装部署与常用操作
- 验证码的实现VerifyCodeUtils
- ArrayList源码分析