JavaScript 对象转换之 toString 和 valueOf

发布于 2021-11-02 12:41:24 字数 4235 浏览 1160 评论 0

开始这个话题之前,我们先看一下下面的几个例子:

parseInt(0.0000004)  // 4
![]==[] //true
['x','y'] == 'x,y' //true
alert({name:'mofei'})  //"[object Object]"

结果有时候会让我大吃一惊,这是为什么呢?今天就和大家讨论一下 JavaScript 的对象转换。

基础类型

先让我们了解一下 JavasScript 转换的 原始类型(primitive value):

  • Number
  • String
  • Boolean

在JavaScript进行对比或者各种运算的时候会把对象转换成这些类型,从而进行后续的操作,下面逐一说明:

String 转换

在某个操作或者运算需要字符串的时候,往往会触发Object的String转换,举个例子

var obj={name:'Mofei'}
var str = ' ' + obj
console.log(str);  //   [object Object]

上述的例子中,在字符串相加的过程中,系统调用了 obj 的 String 转换,具体规则如下:

  1. 如果 toString 方法存在并且返回 原始类型,返回 toString 的结果。
  2. 如果 toString 方法不存在或者返回的不是“原始类型”,调用 valueOf 方法,如果valueOf方法存在,并且返回“原始类型”数据,返回valueOf的结果。
  3. 其他情况,抛出错误。

我们可以用下面的方法简单的证明上面的规则:

首先我们尝试改写一个对象的 toString 方法

var a={
    toString:function(){
        console.log('调用了 a.toString');
        return '111';
    }
}
alert(a);

//调用了 a.toString
// 111

可以看到,系统在执行 ' '+a 的时候,自动调用了 a 的 toString 方法,将 a(Object) 转换成了 String。

下面我们尝试证明如果toString()方法不可用的时候系统会调用 valueOf() 方法

var a={
    toString:function(){
        console.log('调用了 a.toString');
        return '111';
    },
    valueOf:function(){
        console.log('调用了 a.valueOf');
        return '111';
    }
}
alert(a);

//调用了 a.toString

这里我们增加了valueOf方法,但是发现系统并没有调用,这是因为,第一步toString返回的是原始类型,我们尝试把第一步返回的值改成一个对象 {}

var a={
    toString:function(){
        console.log('调用了 a.toString');
        return {};
    },
    valueOf:function(){
        console.log('调用了 a.valueOf');
        return '111';
    }
}
alert(a);

// 调用了 a.toString
// 调用了 a.valueOf

从结果可以看到,当toString不可用的时候,系统会再尝试valueOf方法,我们继续修改valueOf方法,把valueOf方法也改成返回对象 {}

var a={
    toString:function(){
        console.log('调用了 a.toString');
        return {};
    },
    valueOf:function(){
        console.log('调用了 a.valueOf');
        return {};
    }
}
alert(a);

// 调用了 a.toString
// 调用了 a.valueOf
//  Uncaught TypeError: Cannot convert object to primitive value

可以发现,如果 toString 和 valueOf 方法均不可用的情况下,系统会直接返回一个错误。

Number 转换

下面说说 Number 转换,同理,当需要使用 Number 时,( 如 Math.sin() )等,解释器会尝试将对象转换成Number对象。

通常有如下的情况会触发 Number 转换

  1. 方法参数需要 Number 的时候,如 Math.sin(obj) 等
  2. 对比的时候,如 obj == 'abc'
  3. 运算的时候,如 obj + 123

转换规则如下:

  1. 如果valueOf存在,且返回“原始类型”数据,返回valueOf的结果。
  2. 如果toString存在,且返回“原始类型”数据,返回toString的结果。
  3. 报错。

可以参考String转换的方法进行验证,这里只列出一种典型的方法,其他的可以自己动手来修改

var a={
    toString:function(){
        console.log('调用了 a.toString');
        return 12;
    },
    valueOf:function(){
        console.log('调用了 a.valueOf');
        return {};
    }
}
a+1
//调用了 a.valueOf
//调用了 a.toString
//13

可以看到,这里我们改写了 valueOf 和 toString 方法,系统在调用 valueOf 方法之后发现返回的不是 原始类型 数据,于是又尝试调用了 toString 方法,并返回了该方法返回的值12,最后+1变成了13。

Boolean 转换

在进行布尔比较的时候,比如 if(obj) , while(obj) 等等,会进行布尔转换,布尔转换遵循如下规则:

布尔值
true/falsetrue/false
undefined,nullfalse
Number0,NaN 对应 false, 其他的对应 true
String""对应false,其他对应true('0'对应的是true)
Objecttrue

举个比较典型的例子

[] == ![]  //true

// 首先第一步右边的是逻辑判断![],说以先转成boolean
// [] == !true
// [] == false
// 左边不是原始类型,尝试把左边转成原始类型,变成
// '' == false
// 转成Number
// 0 == 0

总结

通过上述的介绍,一开始提到的问题应该都很容易得到答案了。

parseInt(0.0000004)  // 4
![]==[] //true
['x','y'] == 'x,y' //true
alert({name:'mofei'})  //"[object Object]"

关于这些转换,有时确实很让人费解,不过在了解原理之后,就会变得很容易了。有什么问题,可以给我留言,我会第一时间回复。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

终遇你

暂无简介

0 文章
0 评论
687 人气
更多

推荐作者

已经忘了多久

文章 0 评论 0

15867725375

文章 0 评论 0

LonelySnow

文章 0 评论 0

走过海棠暮

文章 0 评论 0

轻许诺言

文章 0 评论 0

信馬由缰

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文