js显式类型转换、隐式类型转换及相关==操作符的总结(一)

本篇文章根据《你不知道的javascript  中卷》及ECMAScript标准总结而来,如有错误还请指正。

一、Toprimitive运算符

1、介绍

 ToPrimitive 运算符接受一个值,和一个可选的 期望类型 作参数。ToPrimitive 运算符把其值参数转换为非对象类型。如果对象有能力被转换为不止一种原语类型,可以使用可选的 期望类型 来暗示那个类型

以上是ECMAScript规范中文版对于Toprimitive运算的介绍。通俗的说,js中的对象在进行类型转换的时候,会进行toptimitive操作转换成简单类型的值(除Symbol值)。所有看起来觉得奇怪的结果都是toprimitive运算带来的。

2、toprimitive运算规则

 ToPrimitive 运算符接根据下表完成转换。

输入类型结果
Undefined结果等于输入的参数(不转换)。
Null结果等于输入的参数(不转换)。
Boolean结果等于输入的参数(不转换)。
Number结果等于输入的参数(不转换)。
String结果等于输入的参数(不转换)。
Object返回该对象的默认值。(调用该对象的内部方法[[DefaultValue]]一樣)。

所以,对于对象来说,toprimitive操作就是调用对象内部的[[DefaultValue]]方法。同时,toprimitive还有一个参数,会传递给[[DefaultValue]]方法。

3、[[DefaultValue]]方法

[[DefaultValue]]方法是对象内部的方法,接收两个参数,一个是要转换的对象,一个是类型(书中被称作上下文)。类型参数的可选值有两个:number和string。

如果参数是string,会先执行toString方法。如果返回对象,那么就会执行valueOf方法。如果valueOf方法仍返回对象,会报TypeError异常。如果在执行valueOf方法或者toString方法的过程中,返回非Symbol类型的简单值,会将该简单值返回,并调用String()方法,将调用String()的结果作为最终的返回值。如果返回Symbol值,那么也会报错。(记住,显示调用String()方法可以将Symbol值转换为字符串,但是这里是隐式调用,会报 Uncaught TypeError: Cannot convert a Symbol value to a string 异常)。

类似的,如果参数是number,那么会先执行对象的valueOf方法。如果返回对象,那么就会执行toString方法。如果toString方法仍返回对象,会报TypeError异常。如果在执行valueOf方法或者toString方法的过程中,返回非Symbol类型的简单值,会将该简单值返回,并调用Number()方法,将调用Number()的结果作为最终的返回值。如果返回Symbol值,那么也会报错。(这里稍微有点不同。显式调用Number()将Symbol值转换为数字也会报 Uncaught TypeError: Cannot convert a Symbol value to a number异常)。

除去自定义了valueOf方法的对象,对象的valueOf方法都返回自身。(Date对象返回自1970.1.1以来的毫秒数)。toString()方法类似(数组结果是成员拼接的、以,分割的字符串,Date对象结果是国际标准时间,其他对象结果是[object Object])。

用一张流程图表示:

图上的返回结果,最终还会调用String()或者Number()得到最终的结果。

二、显式类型转换

1、toString(转换成字符串)

null转换为"null",undefined转换为"undefined",true转换为"true",false转换为"false",常规数字转换为对应的字符串(无限大会得到"infinity",过大或过小会得到科学计数法的字符串,详细规则请参考ECMAScript中文版 9.8.1),Symbol值转换成对应的值。

重点需要说的是对象,会进行抽象化操作,即进行toprimitive运算,得到最终的字符串或者抛出异常

调用String()方法将对象转换成字符串时进行了toprimitive操作,类型string。具体流程参考上面的流程图及文字说明。

简单的例子:

let obj = {
        valueOf() {
          return new Boolean(111);
        },
        toString() {
          return "aaa";
        }
      };
      let obj1 = {
        valueOf() {
          return 2;
        },
        toString() {
          return [];
        }
      };
      let obj2 = {
        valueOf() {
          return new Boolean(111);
        },
        toString() {
          return [];
        }
      };
      console.log(String(obj));
      console.log(String(obj1));
      console.log(String(obj2));

2、toNumber(转换成数字)

调用Number()方法,null结果是0,undefined结果是NaN,true结果是1,false结果是0。

字符串的话,如果是数字+空格组成的字符串且空格只出现在字符串开头或结尾,那么结果是该字符串对应的数字,否则结果是NaN。Number()的参数是Symbol值时会抛出异常。(与String()不同)

Number()参数为对象时,进行toprimitive操作,类型是number,流程参考上面的流程图和文字说明。

几个简单的例子:

let obj = {
        valueOf() {
          return [];
        },
        toString() {
          return 2;
        }
      };
      let obj1 = {
        valueOf() {
          return 2;
        },
        toString() {
          return [];
        }
      };
      let obj2 = {
        valueOf() {
          return new Boolean(111);
        },
        toString() {
          return [];
        }
      };
      console.log(Number(obj));
      console.log(Number(obj1));
      console.log(Number(obj2));

3、toBoolean(转换成布尔值)

显式转换成布尔值时,只有七个值会转换成成false,其他均转换为true,所以只需要记这六个值就可以了。方式包括!取反、Boolean()方法

这六个值分别为:0(包括+0和-0)、false本身、NaN、null、undefined、“”(空字符串)和NaN

三、隐式类型转换

通常,隐式类型转换指不调用如Number()、String()等方法而发生的类型转换,包括操作符、判断等等。

1、string与number的转换

隐式转换成字符串通常发生在+操作符的时候。但是,并不是+操作符就一定会发生隐式类型转换成字符串。根据ECMAScript规范,如果+操作符两边的值至少有一个是字符串或者能够通过toprimitive转换成字符串时,+操作符执行的是字符串的拼接,即+两边的值都会转换成字符串,其中对象执行toprimitive操作,类型是number(Date对象除外。Date对象的toprimitive操作的默认类型是string)。否则+执行的是数字的相加操作。

下面是几个简单的例子:

      let obj = {
        valueOf() {
          return "1";
        },
        toString() {
          return 2;
        }
      };
      let obj1 = {
        valueOf() {
          return 2;
        },
        toString() {
          return [];
        }
      };
      let obj2 = {
        valueOf() {
          return new Boolean(111);
        },
        toString() {
          return [];
        }
      };
      console.log(1 + obj);//验证普通对象toprimitive操作的类型是number
      console.log(1 + obj1);//验证+操作符的规则
      console.log(111 + new Date());//验证Date对象的toprimitive操作的类型是string

除此之外,一些数学操作符会将其他类型转换成number类型。例如,单独的+操作符,其他-、*、/,位运算符等等。与Number()的过程一样。true转换成1,false转换成0。注意位运算符的一些特殊表现。

 let obj = {
        valueOf() {
          return 1;
        },
        toString() {
          return 0;
        }
      };
      let obj1 = {
        valueOf() {
          return 2;
        },
        toString() {
          return [];
        }
      };
      let obj2 = {
        valueOf() {
          return new Boolean(111);
        },
        toString() {
          return [];
        }
      };
      console.log(-obj);
      console.log(~~obj);

2、转换成boolean

隐式类型转换成boolean的情况主要包括:

(1)if语句的条件判断表达式;

(2)for循环中的条件判断表达式(第二个);

(3)while和do while的条件判断表达式;

(4)三目运算符(?:)的条件判断表达式;

(5)逻辑运算符&&、||左边的表达式

隐式类型转换成boolean的规则与显示转换一致,即只有那六个值会被转换成false。

四、结语

以上就是关于js中类型转换的介绍,类型转换也带来另一个问题,即==操作符中也会发生类型转换。限于篇幅,下一篇文章再介绍==操作符的转换规则。地址在这 戳我

参考资料:ECMAScript 中文版 《你不知道的javascript  中卷》

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值