博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
类型转换
阅读量:5058 次
发布时间:2019-06-12

本文共 4795 字,大约阅读时间需要 15 分钟。

 
介绍显式和隐式强制类型转换之前,先了解一下 字符串、数字和布尔值之间类型转换的基本规则。 ES5  规范中定义了
一些 “ 抽象操作 ” 和转换规则。先介绍 ToString 、 ToNumber , ToBoolean , ToPrimitive 以及 [[defaultValue]] 。
 
/**************************************************************************************/
[[defaultValue]]
  -------------------------------------------------------
  当用字符串 hint 调用 O 的 [[DefaultValue]] 内部方法,采用以下步骤: 

  1. 令 toString 为用参数 "toString" 调用对象 O 的 [[Get]] 内部方法的结果。

  2. 如果 IsCallable(toString) 是 true,则

        1. 令 str 为用 O 作为 this 值,空参数列表调用 toString 的 [[Call]] 内部方 法的结果。

        2. 如果 str 是原始值,返回 str。

  3. 令 valueOf 为用参数 "valueOf" 调用对象 O 的 [[Get]] 内部方法的结果。

  4. 如果 IsCallable(valueOf) 是 true,则

        1. 令 val 为用 O 作为 this 值,空参数列表调用 valueOf 的 [[Call]] 内部方 法的结果。

        2. 如果 val 是原始值,返回 val。

  5. 抛出一个 TypeError 异常。

 

  -------------------------------------------------------

  当用数字 hint 调用 O 的 [[DefaultValue]] 内部方法,采用以下步骤:

  1. 令 valueOf 为用参数 "valueOf" 调用对象 O 的 [[Get]] 内部方法的结果。

  2. 如果 IsCallable(valueOf) 是 true,则

        1. 令 val 为用 O 作为 this 值,空参数列表调用 valueOf 的 [[Call]] 内部方 法的结果。

        2. 如果 val 是原始值,返回 val。

  3. 令 toString 为用参数 "toString" 调用对象 O 的 [[Get]] 内部方法的结果。

  4. 如果 IsCallable(toString) 是 true,则

        1. 令 str 为用 O 作为 this 值,空参数列表调用 toString 的 [[Call]] 内部方 法的结果。

        2. 如果 str 是原始值,返回 str。

  5. 抛出一个 TypeError 异常。

  -------------------------------------------------------

  当不用 hint 调用 O 的 [[DefaultValue]] 内部方法,O 是 Date 对象的情况下 仿佛 hint 是字符串一样解释它的行为,除此之外仿佛 hint 是数字一样解释它 的行为。

  上面说明的 [[DefaultValue]] 在原生对象中只能返回原始值。如果一个宿主对象 实现了它自身的 [[DefaultValue]] 内部方法,那么必须确保其 [[DefaultValue]] 内部方法只能返回原始值

/**************************************************************************************/
 
ToPrimitive
  ToPrimitive 运算符接受一个值,和一个可选的  期望类型 作参数
  ToPrimitive 运算符把其值参数转换为非对象类型。如果对象有能力被转换为不止一种原语类型,可以使用可选的  期望类型 来暗示那个类型。
  
  ECMA-262 规范中定义 ToPrimitive 转换规则如下
  输入类型    结果
  Undefined    结果等于输入的参数(不转换)。
  Null     结果等于输入的参数(不转换)。
  Boolean     结果等于输入的参数(不转换)。
  Number     结果等于输入的参数(不转换)。
  String     结果等于输入的参数(不转换)。
  Object     返回该对象的默认值。 (调用该对象的内部方法[[DefaultValue]]一样)
  
  附: 对象内部属性之:   取值范围    说明
   [[PrimitiveValue]]  primitive  与此对象的内部状态信息关联。对于标准内置对象只能用 Boolean, Date, Number, String 对象实现 [[PrimitiveValue]] 
 
/**************************************************************************************/
toString 它负责处理非字符串到字符串的强制类型转换
  undefined: "undefined"
  null: "null"
  Boolean: true          => "true"
               false         => "false"
  Number: NaN          => 'NaN'
               +0, -0       => "0"
               <0            => 返回连接 '-'和 toString(-m) 的字符串
               无限大       => "Infinity"
               其他          => "一大堆的运算规则下, 返回值的十进制表示"
  String: 不转换
  Object: 调用 toPrimitive (输入参数, 暗示 字符串类型)
         调用 toString(result1)
             返回 result(2)
 
/**************************************************************************************/
ToNumber 
  undefined: NaN
  null: +0
  Boolean: true          => 1
               false         => 0
  Number: 不转换
  String: 规则非常多, 不再罗列, 如果无法解释, 那么 toNumber 的结果为 NaN
  
  Object: 设 原始值 为 toPrimitive (输入参数, 暗示 数值类型) 
                 返回 toNumber( 原始值 )
 
 
思考以下代码: 

var ob = {

  toString: function () {
    return null; // 返回值必须是 primitive, 否则抛出错误
  },
  valueOf: function () {
    return '444';
  }
}

console.log(ob + 'aaa', String(ob)) // 444aaa null

console.log(ob + 123, Number(ob)); // 444123 444

// ...

 

/**************************************************************************************/
 ToBoolean
  输入类型  结果
  Undefined  false
  Null   false
  Boolean   结果等于输入的参数(不转换)
  Number   如果参数是 +0, -0, 或 NaN,结果为 false; 否则结果为 true
  String   如果参数参数是空字符串(其长度为零),结果为 false,否则结果为 true。
  Object   true
  
  toBoolean 有些特殊, 比如 var v1 = new Boolean(false); Boolean(v1) // true;
  个人认为: toBoolean 操作对原始值 (primitive) 的转换遵循规范上规则; 对于非原始值即转换为 true;
      原始值 primitive: 指 Undefined, Null, Boolean, String, Number
      原始值直接代表语言实现的最底层的数据。
 /**************************************************************************************/
 
  
 
 
 说回正题:
  强制类型转换:
   a. 显示强制类型转换:
    
    即强制将一个类型值转换为另一个类型值; 比如我们常用的: Number('123'); //123, String(345); //'345'
    1. 字符串和数字之间的显式转换: 通过 String(..) 和 Number(..) 这两个内建函数来实现的;
     String(..) 遵循上面讲的 ToString 规则
     Number(..) 遵循上面讲的 ToValue 规则
    
    2. 显式转换为布尔值:
     Boolean() 遵循上面讲的 toBoolean 规则
    
     
   
   b. 隐式强制类型转换:
    指的是那些隐蔽的强制类型转换; 比如 a == 1 这种操作; 隐式强制类型转换 可以减少冗余,让代码更简洁
    而且在方方面面, 可能都有涉及到隐式强制类型转换:
    比如:
     
'111' == 111; // true  一个是数字一个是字符串, 如何比较相等; 转换值类型应该是都转换为数值再比较; 还是都转换为字符串再作比较;if ('111') {...}   //if 中本应该是一个布尔值, 字符串如果判断, 又需要将字符串转换为布尔值'345' + 12; // 34512  数字和字符串如何相加,又如何转换值类型; 到底是认为两个都是字符串, 执行字符串拼接; 还是认为两个都是数字, 执行数学运算;'222' % 2; // 0 字符串又如何能够进行模运算, 所以又需要将值转换为数字再进行运算;~'222'; // -233     先对 '222' 值 toNumber得到 222 再 ToInt32 转换为32位整数, 再执行字位操作 ~(对每一个字位进行反转), 得到 -223; ['2'] + 333; // 2333 类似的...

 

   
    这里面涉及到了几乎所有的运算符
    如:
     一元位运算:
      1. 前自增
      2. 前自减
      3. 一元 + 运算符
      4. 一元 - 运算符
      5. 按位非运算符
      6. 逻辑非运算符
     
     乘法运算符
      1. 使用 * 运算符
      2. 使用 / 运算符
      3. 使用 % 运算符
     
     加法运算符
      1. 加号运算符 +
      2. 减号运算符 -
     
     位运算移位运算符,
      ...
     
     比较运算符:
      1. < , <=
      2. > , >=
      3. 抽象关系比较: 详细定义请见 ECMA-262规范中定义
     
     等值运算符:
      1. ==
      2. !=
     
     还有二元逻辑运算 (&&, ||), 条件运算 (?) 里面都会涉及到类型转换。但无论怎样, 类型转换都离不开 toNumber, toString, toBoolean 这几种操作;
     到底是应该 toNumber, 还是 toString, 亦或 toBoolean, 得视具体情况来定。
     其他更加详细的内容, 请参阅规范或是其他书籍。
     
     
     
     
     
 <hr>
     
 参考:
  << ECMA-262-5.1 中文版 >>
  << 你不知道的 javascript (中卷) >>

转载于:https://www.cnblogs.com/liuyingde/p/10551230.html

你可能感兴趣的文章
Mongo自动备份
查看>>
求助大神!怎样批量删除数据库表中某个字段中同样的一段字符!
查看>>
VMWARE虚拟机无法访问的三种方法分析
查看>>
enq: SQ - contention
查看>>
cer证书签名验证
查看>>
面向对象设计
查看>>
ant 安装
查看>>
新手Python第一天(接触)
查看>>
vue路由动态加载
查看>>
【原】UIWebView加载本地pdf、doc等文件
查看>>
iOS中ARC内部原理
查看>>
【bzoj1029】[JSOI2007]建筑抢修
查看>>
synchronized
查看>>
你不得不了解的应用容器引擎---Docker
查看>>
easyui datagrid 弹出页面会出现两个上下滚动条处理办法!
查看>>
迭代器和生成器
查看>>
MYSQL分区表功能测试简析
查看>>
codevs 1080 线段树练习
查看>>
JS模块化库seajs体验
查看>>
Android内核sysfs中switch类使用实例
查看>>