• 【javascript基础】toString、valueOf、转换 【译】


    js中的对象可以被转换成以下3个基本数据类型:

    1、Nunber

    2、String

    3、Boolean

    对上述转换的理解,我们可以绕过缺陷,并写出更整洁的代码。

    一、字符转换

          当需要一个对象的字符表示时候,将发生字符传唤。

    e.g.在alert中输出obj

    var obj = { name: 'John' }

    alert(obj) // [object Object]

          当然,也可以显示转换,String(obj);

    对象转换成字符串的逻辑 

          对象转换成字符串的逻辑如下:

                   1、如果对象有toString方法,则调用该方法,并返回相应的结果;

                    PS:代码通常会执行到这,因为在所有对象中都有toString方法。

                   2、如果对象有valueOf方法,则调用该方法,并返回相应的结果;

                   3、否则抛出异常。

          通常,所有对象toString方法,内置对象都有自己toString实现:

           e.g.

    alert( {key: 'value'} ) // toString for Objects outputs: [object Object]
    alert( [1,2] )          // toString for Arrays lists elements "1,2" 
    alert( new Date )       // toString for Dates outputs the date as a string
    自定义toString

    e.g.

    var user = {

      firstName: 'John',

      toString: function() {
        return 'User ' + this.firstName 
      }
    }

    alert( user )  // User John
    二、数字转换

    在JavaScript中还有另一种转换,虽然没有toString用的广泛 ,但在JS引擎内部,用得更频繁。

    数字转换的两种主要情况:
    1、函数需要数字,e.g.: Math.sin(obj) isNaN(obj)包括算术运算符: +obj

    2、用于比较,e.g. obj == 'John'

    PS:下面两种比较不会发生类型转换,

          a)在严格比较(===)中,不会发生任何的类型转换,

          b)在非严格比较中,如果参数都是对象,不会发生类型转换,通常,如果两个对象引用统一对象,则返回true.

    也可以通过显式转换Number(obj)
    对象转换成数字的逻辑 

         步骤 如下:

                   1、如果对象有valueOf方法,则调用该方法,并返回相应的结果;

                   2、否则如果对象有toString方法,则调用该方法,并返回相应的结果;

                   3、否则抛出异常。

    在内置对象,Date支持数字和字符串转换 :

    alert( new Date() ) // The date in human-readable form
    alert( +new Date() ) // Microseconds till 1 Jan 1970
    但大多数的对象没有valueOf , 这意味着数字转换基本上调用toString方法
    自定义valueOf

    e.g.

    var room = { 

      num: 777,

      valueOf: function() {
        return this.num
      }
    }

    alert( +room )  // 777
    如果对象中没有valueOf方法,将会调用toString方法
    var room = { 

      num: 777,

      toString: function() {
        return this.num
      }
    }

    alert( room / 3 )  // 259
     
    数字转换

    数字转换并不意味着必须返回一个数字,但必须是以一个基本的数据类型,但它的具体类型没有任何限制。

    因此,将对象转换成数字的一个很好的办法是:通过+操作符实现

    e.g.

    var arr = [1,2,3]

    alert( arr + '' ) 
    // first tries arr.valueOf(), but arrays have no valueOf
    //
     so arr.toString() is called and returns a list of elements: '1,2,3'
    由于历史的原因, new Date + ''也返回一个Date字符串形式,即使new Date也有valueOf方法 。 这是一个例外。
    其他的数学函数不仅进行数字转换,强制转换成一个数字。 例如一元加法+arr会给NaN
    alert( +[1,2,3] ) // [1,2,3] -> '1,2,3' -> not a number


    全等/比较测试中的转换

     非严格比较,将比较以数字比较。

    当一个参数是基本类型的时候,对象将被强制转换,

     e.g.

    if (obj == true) { ... }
    如果参数都是对象,不会发生类型转换,通常,如果两个对象引用统一对象,则返回true.

    下面的比较将会被转化为基本类型

    var a = { 
      valueOf: function() { return  1 }
    }
    var b  = { 
      valueOf: function() { return  0 }
    }

    alert( a > b )  // 1 > 0, true

    下面的为什么会返回true

    alert( ['x'] == 'x' )

     解决方案:

    左边是数组,右边是基本类型,因此数组将被数字转换,由于数组没有valueOf方法,于是调用toString方法,

    alert( ['a','b'] + '' )   // 'a,b'

     PS:

    下面的同样的逻辑

    ['x','y'] == 'x,y'
    [] == ''

     

    二、布尔值转换
    还有一个标准的JavaScript的转换,在ecmascript262规范中称为[[toBoolean]]

    如果发生在布尔上下文中,如if(obj) while(obj)等。

    对象可能无法实现自己的这种转换,也没有其他特殊的方法。 相反,有一个硬编码的换算表:

    PS:不像其他的编程语言,比如PHP,'0'在JS中返回的是true

    在下面的例子中发生数字转换

    alert( [0] == 0 )  // true
    alert( "\n0\n" == 0 ) // true
    alert( "\n0\n" == false ) // true
    因此,人们可能会猜测, [0]"\n0\n"是false,因为他们等于0
    但现在让我们来看看左侧部分在布尔上下文中的是如何的:
     
    if ([0]) alert(1)  // 1, if treats [0] as true
    if ("\n0\n") alert(2) // 2, if treats "\n0\n" as true
     
     
    这是可能的, a == b ,但在布尔上下文中, atruebfalse
    想想,下面为什么会相等
    alert( [] == ![] ) // true


     解决:

    1、对两边求值,右边是![],将会被转换成一个布尔值,true,算完之后,表达式变成:

    []==false;

    2、左边是数组,右边是布尔值,按照规则,将false转换成0,数组也将进行数字转换,转换为0

    0 == 0;;;;;;

     3、结果很显然了

     

     计算下下面表达式,完成时,看下下面的解决办法:

    6 / "3"
    "2" * "3"
    4 + 5 + "px"
    "$" + 4 + 5

    "4" - 2

    "4px" - 2

    7 / 0

    {}[0]

    parseInt("09")

    5 && 2

    2 && 5

    5 || 0

    0 || 5
    6 / "3" = 2
    "2" * "3" = 6
    4 + 5 + "px" = "9px"
    "$" + 4 + 5
 = "$45"
    "4" - 2
 = 2
    "4px" - 2
 = NaN
    7 / 0
 = Infinity
    {}[0]
 = undefined
    parseInt("09")
 = "0" or "9" // octal or decimal, depends on the browser
    5 && 2
 = 2
    2 && 5
 = 5
    5 || 0
 = 5
    0 || 5 = 5

    总结

    在JavaScript中有三个转换,这取决于具体情况:

    1. 字符串输出,使用toString
    2. 数字:数学函数,操作符,使用valueOf 后使用 toString
    3. 布尔值:根据下表转换。

    这是不同于大多数其他编程语言,当你了解之后,其实很简单。

    最准确的转换算法,参考规范:ECMA-262第五版,特别是11.8.5(关系比较),和11.9.3(相等比较)和9.1(toPrimitive)和9.3(toNumber)。

    参考:

    Conversion, toString and valueOf  http://javascript.info/tutorial/object-conversion

  • 相关阅读:
    IOS 作业项目(1) 关灯游戏 (百行代码搞定)
    Object-C 基础笔记5---Category
    Object -c基础知识(5)--release 之后 retainCount为何为1
    Foundation--NSString , array and Dictionary
    Foundation--结构体
    Object-C 基础笔记4---ARC内存管理
    141. Linked List Cycle
    139. Word Break
    138. Copy List with Random Pointer
    133. Clone Graph
  • 原文地址:https://www.cnblogs.com/sniper007/p/2777378.html
Copyright © 2020-2023  润新知