JavaScript中的toString()和valueOf()

两者的关系

  • javaScript中toString()函数和valueOf函数是Object对象生来就拥有的(undefined和null没有toString()和valueOf()方法),并且他们还可以允许我们重写。
  • 举个栗子
var arr = [1,2,3];  
alert(Array.isArray(arr.valueOf()));  
alert(Array.isArray(arr.toString()));  

结果是第一个是true而第二个是false,原因是valueOf()调用完以后还是返回一个数组,这个数组被alert的时候会调用toString()函数;所以不是valueOf()和toString()函数相同,而是alert时间接调用了toString()函数!

对象向基本数据类型的转换的规则

1.vauleOf优先于toString()被调用---------当对象作为操作数的时候(Date类型的除外)
var x="10";
var a=+x;
console.log(typeof a);     //number
var b=a+x;
console.log(typeof b);    //string
var object={};
object[a]=10000;
console.log(object[10]);  //10000
  • "+"号作为一元运算符---- 在这个运算符下,对象向基本数据类型的转换规则:
    (1).当操作数是基本数据类型的时候,调用Number()函数,将其转换为数值
    (2). 当操作数是对象的时候,调用对象的toString或者valueOf函数,将对象转化为基本数据类型的值,然后再对该值调用Number()函数。
    所以,根据以上的转换规则,上述的输出结果为 number 也就合理了.
  • 但是,第二条转换规则里,蕴含了一个好大的坑啊:到底是调用toString()还是valueOf(),要是两个函数都能将对象转换为基本数据类型呢(比如Date类型的对象),你又调用谁呢?
  • 类似这样
var x = {
  toString: function () {
    return '0';
  },
  valueOf: function () {
    return 1;
  }
}
var a = + x;  //到底调用的是toString()还是valueOf()呢?,在 + 号作为二元运算符的部分,会给出解释
console.log(a);
  • “+”号作为二元运算符 ----- 在这个运算符下,对象向基本数据类型的转换规则:
    当“+”号作为二元运算符的时候情况就比较复杂了,因为"+"号可以当做字符串的连接,也可以当做数字的相加减。大约有以下规律:
//伪代码,
a + b运算转换规则:
var Pa = toPrimitive(a);
var pb = toPrimitive(b);
if ((Pa is String) || (Pb is String)) {
  return contact(a, b)
}
if ((Pa is Number) && (Pb is Number)) {
  return a+b;
}
 throw error;
 //注: toPrimitive 是将操作数转化为基本数据类型,优先调用valueOf,若得到基本数据类型,则结束,否则继续掉用toString()。(也就是说valueOf的优先级高于toString())
  • 即:含有字符串就是拼接,全为数字则为加法
  • +号作为一元运算符转换规则其实和其作为二元运算符差不多,转化为基本数据类型的时候总是优先调用valueOf()。
var test = {
   valueOf: function () {
     return 1;
    },
   toString: function () {
     return '0';
    }
}
console.log( + test);   //1
var result = test + test;
console.log(result);  //2
  • 在操作数运算的时候(无论是一元的还是二元的运算),数据类型之间的转换总是优先调用valueOf()函数,但是“+”号在作为二元运算符时,这种优先顺序在应用于Date类型的对象时,被逆转了(toString的优先级较高)。
  • 谨记:Date类型是一个特例,当且仅当在+号运算,且“+”号作为二元运算符时,toString()优先调用,比如下面这样
var date=new Date();
console.log(+date);  //仍然优先调用valueOf  
console.log(date+"toString优先被调用");
//输出结果:
// 1421293488713
//Thu Jan 15 2015 11:44:48 GMT+0800toString优先被调用

toString()优先于valueOf()被调用 ------当你想要输出结果是字符串的时候

  • 当访问Object类型对象的变量,我们用[] 这种方括号访问的时候,方括号的内容总是优先转化为字符串,也就是优先调用 toString()函数。
 1   var test = {
 2   toString: function () {
 3     return '0'
 4   },
 5   valueOf: function () {
 6     return 1;
 7   }
 8 };
 9 
10 var object={};
11 object[test]=1000;
12 console.log(object);  // 输出结果:Object { 0=1000}


[a]以这种形式访问的时候:
var Pa=toPrimitive(a);
  if(Pa is prmitive){
    var str=String(Pa);
    }else{
        throw error;//cannot convert to string
    }
[str]//str为字符串的形式
//注: toPrimitive()此时优先调用toString()函数,若结果为基本类型,返回,否则继续调用valueOf(); 
  • 由上面可以看出,toString和valueOf这两个函数在转换的时候都是可能被调用的,只是在不同的环境下,调用的优先级不一样而已。这些对于我们程序员来说,可能是透明的,但是对于解释器说,它们干的活可就多了...一句话归结:解释器总是根据语境尽可能的转化为我们想要的结果。换句话说:
      对象在作为操作数时,解释器总是优先调用valueOf()--(Date类型的对象在二元“+”运算时例外),而其他情况,解释器总是认为我们想要的是字符串,所以会优先调用toString()..
    注:Date类型的对象之所以会在二元+运算时优先调用toString(),也是因为我们大多数情况下, 时间总是和字符串连接使用,而时间和一个数字相加的情况好少,所以Date类型中,toString()优先级才比较高。
    正是因为解释器总想完美的输出我们想要的结果,才会造成这种杂乱的现象和规则出现。天下间本没有完美的事物,矛和盾总是相依相存。
    懂得规则,才能利用规则,回过头来看一下我们在最开始所出的题目吧。是不是就是对这些规则的合理利用呢。
    题外话: 写这篇文章就是为了表明基础知识的重要性,并非追求一个稀奇古怪的程序,程序员追求的应该是通俗易懂的代码(大道至简)而不是这些看起来四不像的程序,切记本末倒置!

备注: toLocaleString()这个函数是实现字符串的本地化的输出,一般和toString()输出的结果相同,没什么特殊的,就是一个普通的函数。在Date类型中,这个函数被重写了

转自:https://blog.csdn.net/shaofei63/article/details/42743245

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,776评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,527评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,361评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,430评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,511评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,544评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,561评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,315评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,763评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,070评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,235评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,911评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,554评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,173评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,424评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,106评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,103评论 2 352

推荐阅读更多精彩内容

  • 函数和对象 1、函数 1.1 函数概述 函数对于任何一门语言来说都是核心的概念。通过函数可以封装任意多条语句,而且...
    道无虚阅读 4,551评论 0 5
  • 运算符是处理数据的基本方法,用来从现有的值得到新的值。JavaScript 提供了多种运算符,本章逐一介绍这些运算...
    徵羽kid阅读 673评论 0 0
  • 前言 之前面试了几个开发者,他们确实做过不少项目,能力也是不错的,但是发现js基础不扎实, 于是决定写一下这篇ja...
    Vicky丶Amor阅读 1,040评论 3 21
  • 算术运算符 JavaScript 共提供10个算术运算符,用来完成基本的算术运算。 加法运算符:x + y 减法运...
    guyigg阅读 1,178评论 0 1
  • 前言 众所周知, js 是一门弱类型或者说是动态语言。变量没有类型限制,可以随时赋予任意值。 虽然变量的数据类型是...
    更替客户阅读 312评论 0 0