• 类型转换方法


    类型转换的工具方法

    • valueOf:返回这个对象逻辑上对应的原始类型的值。比如说,String包装对象的valueOf(),应该返回这个对象所包装的字符串。
    • toString:返回这个对象的字符串表示。用一个字符串来描述这个对象的内容。

    **所有的对象都会继承到这两个方法。 以下是部分内置对象调用valueOf()的行为: **

    对象返回值
    Array数组本身(对象类型)。
    Boolean布尔值(原始类型)。
    DateUTC 1970 年1月1日午夜开始计算,到所封装的日期所经过的毫秒数(原始类型)。
    Function函数本身(对象类型)。
    Number数字值(原始类型)。
    Object对象本身(对象类型)。如果自定义对象没有重写 valueOf 方法,就会使用它。
    String字符串值(原始类型)。

    由上表可见,valueOf()虽然期望返回原始类型的值,但是实际上有一些对象在逻辑上无法找到与之对应的原始值,因此只能返回对象本身。 toString()则不一样,因为不管什么对象,我们总有办法“描述”它,因此javascript 内置对象的toString()总能返回一个原始string类型的值。 我们自己在重写toString()的时候也应该返回合理的string

    valueOf()toString()经常会在类型转换的时候被javascript引擎内部调用,比如说我们后文会谈到的ToPrimitive。在自定义对象上合理地覆盖valueOf()toString(),可以控制自定义对象的类型转换。


    类型转换的内部方法

    ECMAScript定义了4个有关类型转换抽象操作,它们在javascript 引擎内部使用,进行类型转换。我们不能直接调用这些方法,但是了解这些函数有利于我们理解类型转换的原理。

    • ToPrimitive ( input [ , PreferredType ] ):将input转化成一个原始类型的值。PreferredType参数(期望类型)要么不传入,要么是Number String

      • 如果PreferredType参数是NumberToPrimitive这样执行:

        • 如果input本身就是原始类型,直接返回input

        • 调用input.valueOf(),如果结果是原始类型,则返回这个结果。

        • 调用input.toString(),如果结果是原始类型,则返回这个结果。

        • 抛出TypeError异常。

      • 以下是PreferredType为String时的执行顺序:

        • 如果PreferredType参数是String,则交换上面第2和第3步的顺序,其他执行过程相同。
        • 如果PreferredType参数没有传入:
          • 如果input是内置的Date类型,PreferredType 视为String
          • 否则PreferredType 视为 Number
    • ToBoolean ( argument )

      参数类型结果
      UndefinedReturn false
      NullReturn false
      BooleanReturn argument
      Number仅当argument为 +0, -0, or NaN 时, return false; 否则一律 return true
      String仅当argument是空字符串(长度为0)时, return false; 否则一律 return true
      SymbolReturn true
      ObjectReturn true
    • ToNumber ( argument )

      参数类型结果
      UndefinedReturn NaN
      NullReturn +0
      Boolean如果 argument 为 true, return 1. 如果 argument 为 false, return +0
      Number直接返回argument
      String将字符串中的内容转化为数字(比如"23"->23),如果转化失败则返回 NaN(比如"23a"->NaN
      Symbol抛出 TypeError 异常
      ObjectprimValue = ToPrimitive(argument, Number),再对 primValue 使用 ToNumber(primValue)

      ToNumber(function(){}) 返回 NaN

    • ToString ( argument )

      参数类型结果
      UndefinedReturn “undefined”
      NullReturn “null”
      Boolean如果 argument 为 true, return “true”.如果 argument 为 false, return “false”
      Number用字符串来表示这个数字
      String直接返回 argument
      Symbol抛出 TypeError 异常
      ObjectprimValue = ToPrimitive(argument, hint String),再对primValue 使用 ToString(primValue)

    重写(覆盖):重写继承关系上的方法或属性,也可以理解为自身有某方法去覆盖原型对象的构造函数的该方法

    //返回值[Object Object]	第一个Object表示类型,第二个表示构造函数,调用Object.prototype的toString方法
    console.log(o.toString());
    
    //返回值1,2,3,调用Array.prototype的toString方法
    console.log([1, 2, 3].toString())
    
    • 1
    • 2
    • 3
    • 4
    • 5

    注意: parseIntparseFloatstringnumber 之间的转换(提取方法),而不是类型转换方法。


    显式类型转换(强制类型转换)

    显示类型转换只有Boolean(value)Number(value)String(value)这三个方法;paseIntpasefloat将可以转换的字符串进行提取。

    显式(手动)调用Boolean(value)Number(value)String(value)完成的类型转换,叫做显示类型转换。 其实这三个函数用于类型转换的时候,调用的就是 JavaScript 内部的ToBoolean ( argument )ToNumber ( argument )ToString ( argument )方法。

    注意:toStringToString 是不同的方法

    new String(45);	  //当构造函数使用,将一个值转换为String基本包装类型,ToString
    
    String(45);			// 当普通函数使用,将一个值转换为string值类型,ToString
    
    String.prototype;	// 当函数对象使用	
    
    var arr = [1, 2]
    console.log(arr.toString());    //返回1,2
    console.log(toString(arr)); 	//调用Object的toString,返回[Object, Array]
    console.log(String(arr));       //返回1,2
    // console.log(arr.ToString()); //报错
    // console.log(ToString(arr))   //报错
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    隐式类型转换(自动类型转换)

    js期望得到某种类型的值,而实际在那里的值是其他的类型,就会发生隐式类型转换。系统内部会自动调用我们前面说ToBoolean ( argument )ToNumber ( argument )ToString ( argument ),尝试转换成期望的数据类型。

    常见隐式类型转换规则

    在某些情况下,即使我们不提供显示转换,Javascript 也会进行自动类型转换,主要情况有:

    • 用于检测是否为非数值的函数:isNaN(mix)

      • 该函数会尝试将参数值用Number()进行转换,如果结果为“非数值”则返回true,否则返回false
    • 递增递减操作符(包括前置和后置)、一元正负符号操作符,这些操作符适用于任何数据类型的值,针对不同类型的值,该操作符遵循以下规则(经过对比发现,其规则与Number()规则基本相同):

      • 如果是包含有效数字字符的字符串,先将其用 Number 进行转换再执行加减1的操作;
      • 如果是不包含有效数字字符的字符串,将变量的值设置为NaN
      • 如果是布尔值false,先将其转换为0再执行加减1的操作;
      • 如果是布尔值true,先将其转换为1再执行加减1的操作;
      • 如果是浮点数值,执行加减1的操作;
      • 如果是对象,对它用 Number() 转换,再执行加减1的操作。
    • 加号运算操作符在Javascript也用于字符串连接符,所以加号操作符的规则分两种情况:

      • 如果两个操作值都是数值,其规则为:

        • 如果一个操作数为NaN,则结果为NaN
        • 如果是Infinity+Infinity,结果是Infinity(无穷大)
        • 如果是-Infinity+(-Infinity),结果是-Infinity
        • 如果是Infinity+(-Infinity),结果是NaN
        • 如果是+0+(+0),结果为+0
        • 如果是(-0)+(-0),结果为-0
        • 如果是(+0)+(-0),结果为+0
      • 如果有一个操作值为字符串,则:

        • 如果两个操作值都是字符串,则将它们拼接起来
        • 如果只有一个操作值为字符串,则将另外操作值转换为字符串,然后拼接起来
        • 如果一个操作数是对象、数值或者布尔值,则调用valueOf()-toString()方法取得字符串值,然后再应用前面的字符串规则。对于undefinednull,分别调用String()显式转换为字符串。
        • 可以看出,加法运算中,如果有一个操作值为字符串类型,则将另一个操作值转换为字符串,最后连接起来。
        console.log(2 + [99])	//299
        ToPrimitive([], "number")	//0
        
        • 1
        • 2
    • 乘除、减号运算符、取模运算符,这些操作符针对的是运算,所以他们具有共同性:如果操作值之一不是数值,则被隐式调用Number()函数进行转换。

    • 逻辑操作符!、&&、||

      • 逻辑非操作符,首先通过Boolean()函数将它的操作值转换为布尔值,然后求反。
      • 逻辑与&&操作符,如果一个操作值不是布尔值时,遵循以下规则进行转换:
        • 如果第一个操作数经Boolean()转换后为true,则返回第二个操作值,否则返回第一个值(不是Boolean()转换后的值)
        • 如果有一个操作值为null、NaN、undefined,分别返回null、NaN、undefined
      • 逻辑或||操作符,如果一个操作值不是布尔值,遵循以下规则:
        • 如果第一个操作值经Boolean()转换后为false,则返回第二个操作值,否则返回第一个操作值(不是Boolean()转换后的值)
        • 对于undefinednullNaN的处理规则与逻辑与&&相同
    • 关系操作符<, >, <=, >=,与上述操作符一样返回 Boolean值,关系操作符的操作值也可以是任意类型的,所以使用非数值类型参与比较时也需要系统进行隐式类型转换:

      • 如果两个操作值都是数值,则进行数值比较
      • 如果两个操作值都是字符串,则比较字符串对应的字符ASCII编码值(a=97,A=65,0=48)
      • 如果只有一个操作值是数值,则将另一个操作值转换为数值,进行数值比较
      • 如果一个操作数是对象,则调用 ToNumber方法,结果按照前面的规则执行比较
      • 如果一个操作值是布尔值,则将其转换为数值,再进行比较。

      注:NaN是非常特殊的值,它不和任何类型的值相等,包括它自己,同时它与任何类型的值比较大小时都返回false

    • 相等操作符==,相等操作符会对操作值进行隐式转换后进行比较:

      • 如果一个操作值为布尔值,则在比较之前先将其转换为数值

      • 如果一个操作值为字符串,另一个操作值为数值,则通过Number()函数将字符串转换为数值

      • 如果一个操作值是对象,另一个不是,则调用对象的valueOf(), ToString()方法,得到的结果按照前面的规则进行比较

      • nullundefined是相等的

      • 如果一个操作值为NaN,则相等比较返回false

      • 如果两个操作值都是对象,则比较它们是不是指向同一个对象 (比较两者是否是同一个引用地址)

        var arr1 = [];
        var arr2 = [];
        console.log(arr1 == arr2);		//false
        console.log(0 === -[]);			//true
        console.log(Object.id(0,-[] )); //false
        
        • 1
        • 2
        • 3
        • 4
        • 5

    注意:

    • JavaScript 编程指南中表明尽量不使用 ==,例如:1 “1” 与 1= “1”;

    • JS 中会使用最少的转换次数来满足操作符的操作条件。

  • 相关阅读:
    DELL设备维保查询方法
    Qemu支持ATF + u-boot + linux kernel
    一文彻底搞懂ZAB算法,看这篇就够了!!!
    Vue.js(2): 组件与路由基础指南
    2流高手速成记(之五):Springboot整合Shiro实现安全管理
    django中Models常用的字段及属性介绍
    微信小程序是否可以使用自建SSL证书?
    设计模式-单一职责原则
    开源框架(四):mybatis 两种开发方式 映射开发与注解开发
    深度学习 图像分割综述
  • 原文地址:https://blog.csdn.net/Sandersonia/article/details/132664678