资讯专栏INFORMATION COLUMN

原生JS大揭秘—揭开数据类型转换的面纱

Moxmi / 3304人阅读

摘要:可以将其他类型转成字符串函数可以将任意类型的值转为布尔值。提示空数组空对象转换为布尔型也是。

在JS中数据类型转换有两种
相关资料参阅

官方ecma-5规范
阮一峰老师类型转换
规范对相等==定义

强制类型转换
Number() Number函数将字符串转为数值,要比parseInt函数严格很多,只要有一个字符是非数字(空格、+、-除外),那么就会被转为NaN。

String() 可以将其他类型转成字符串
Boolean() 函数可以将任意类型的值转为布尔值。

隐式类型转换
https://www.jianshu.com/p/b07...
https://www.jianshu.com/p/b16...

哪些情况下会发生隐式类型转换?

不同类型的数据互相运算

对非布尔值类型的数据求布尔值

对非数值类型的使用一元运算符(即"+""-")

重点说明: 操作符"+"是一个比较难搞、比较另类、比较奇葩的东西,"+"有两种使用含义

有字符串时,表示字符串拼接

无字符串时,表示算术加法

简单的来说就是看"+"的两端是否有任一个是字符串,有为"字符串拼接",否则为"算术加法"

隐式类型转换原则

都是数字,直接运算

都是字符串,使用字符对应的ASCII值运算

有一个是boolean值,将boolean值转成数字,true->1或false->0

有一个是数字,将另一个转成数字

只有一个是对象,则先将对象转成原始值,在执行操作

转换过程中如果有NaN出现,则结果是NaN或false

重点说明:null、undefined进行"=="比较时不进行类型转换(但是ECMA规范中定义null==undefined // true ),其他运算操作时会转换。
"=="比较时,只有三种情况为true:
1、null==null
2、null==undefined
3、undefined==undefined
除以上三种情况外其他都不相等,返回false

说到NaN,随便讲一下全局函数isNaN(),我们都知道这个函数判断不准确,为什么呢?什么原因造成的呢?其实isNaN()方法只执行前,会对变量进行隐式类型转换比如isNaN({}),返回true
首先进行隐式类型转换,将{}=>Number,最终得到NaN,所以isNaN({})得到true

引用类型转成原始类型分析

在JS内部定义了4个抽象操作(只能供JS内部使用,我们用户无法操作)

ToPrimitive(obj, [PreferredType])
obj:待转换的对象
PreferredType:待转成的目标类型(只接受Number、String两种类型,默认是空),如果obj是Datesymbol,则PreferredType=String,其余的情况下PreferredType=Number

如果PreferredType=Number,引用类型转化为数字
1、调用valueOf(),如果返回原始值,则结束,如果返回非原始值,则执行第2步
2、调用toString(),如果返回原始值,则结束,如果返回非原始值,则报错

如果PreferredType=String,引用类型转换为字符串
1、调用toString(),如果返回原始值,则结束,如果返回非原始值,则执行第2步
2、调用valueOf(),如果返回原始值,则结束,如果返回非原始值,则报错

引用类型转换为布尔类型,始终返回true

ToNumber(arguments)

ToString(arguments)

ToBoolean(arguments)

在执行隐式类型转换时,会自动调用这四个内部方法
原始值之间相互转换:ToNumber()、ToString()、ToBoolean()
引用值到原始值转换: ToPrimitive()
在执行显示类型转换时,如Number()、String()、Boolean()时,内部还是调用ToNumber()、ToString()、ToBoolean(),如果待转换的是引用类型,则先执行ToPrimitive(),得到原始值,再执行ToNumber()、ToString()、ToBoolean()

这里特别说明:把引用值原始值的过程中JS内部在调用ToPrimitive()方法时,分为两种情况
1、明确指定目标转换类型:按照指定类型去调用toString()/valueOf()方法
2、没有指定目标转换类型:按照obj是否是Date类型,去调用toString()/valueOf()方法

不同类型的对象调用toString()返回值不同:

{} => "[object Object]"

[] => ""

[1,2,3] => "1,2,3"

function(){} => "function(){}"

Date => "Mon Feb 12 2018 15:44:57 GMT+0800 (中国标准时间)"

RegExp => "/d/"正则字面量的字符串

不同类型的对象调用valueOf()返回值不同

Date类型 => 1518421497815 返回自1970年1月1日至现在的时间戳毫秒数

其他的类型 => 一律返回对象自身

JS数据类型之原始值与引用值的转换关系图解

重点说明: 通过new Number()/new String()/new Boolean()得到的是对象(无论传入什么参数),该对象有一个属性[[PrimitiveValue]]`,此属性保存着该对象对应的原始值。

对于包装对象而来,转换成原始值时,有点特殊(不同于{}[]这种类型的对象),

valueOf(): 获取[[PrimitiveValue]]属性的值

toString(): 获取[[PrimitiveValue]]属性值的字符串形式

JS中数据转换图表
原始类型 目标类型(Number) 目标类型(String) 目标类型(Boolean) 目标类型(Object)
undefined NaN "undefined" false throw TypeError
null 0 "null" false throw TypeError
true 1 "true" true new Boolean(true)
false 0 "false" false new Boolean(true)
0 0 "0" false new Number(0)
-0 -0 "-0" false new Number(-0)
NaN NaN "NaN " false new Number(NaN)
Infinity Infinity "Infinity " true new Number(Infinity )
Infinity -Infinity "-Infinity " true new Number(-Infinity )
"7" 7 "7" true new String("7")
"" 0 "" 当且仅当是空字符串(即长度为0)时,才返回false,其他返回true,也就是" "为true new String("")
"7M" NaN "7M" true new String("7M")
"M" NaN "M" true new String("M")
[] 0 "" true []
["7"] 7 "7" true []
{} 先ToPrimitive,再执行以上规则 先ToPrimitive,再执行以上规则 true {}
function(){} NaN true true function(){}

https://www.jianshu.com/p/0af...
提示1:只有空字符串("")、null、undefined、+0、-0 和 NaN 转为布尔型是 false,其他的都是 true。
提示2:空数组、空对象转换为布尔型也是 true。
提示3:null 和 undefined 转换为数字是表现不一,分别为0和NaN。

非数值型转成数值型 非数值 -> 数值的方法有三种

Number()

parseInt()

parseFloat()

parseInt解刨
 ------------------------------------------------------------------------
 描述:是一个内置的函数,
 作用:可以把一个字符串转成整形,parseInt的返回值只有两种情况,a、十进制整数 b、NaN
 有两个参数
   a、第一个参数表示待转换的字符串(必须是字符串,如果不是字符串,则会发生隐式类型转换
      然后对转换后的字符串进行截取
   )

   b、第二个参数表示待转换的字符串的进制(默认是10进制)
      该值的范围介于[2,36],如果进制不在此范围内的,一律返回NaN

      注意:基数如果不是数值,则发生隐式类型转换,如果基数是NaN,则默认基数是10

   特别注意,这里的默认进制10,是有条件的
   条件1,必须没有明确指定进制数
   条件2,待转换的字符串,不是以0或0x打头的

   在字符串以"0"为开始时旧的浏览器默认使用八进制基数。ECMAScript 5,默认的是十进制的基数。
   如果没有明确指定进度,对于"0”打头的字符串在“ES5之前”认为是8进制
                     对于"0”打头的字符串在”ES5之后“认为是10进制

   如果有明确指定数的进制,则以指定的进度为准

   var n=parseInt("11",2) //表示字符串"11"是2进制的数
   var n=parseInt("11",8) //表示字符串"11"是8进制的数
   var n=parseInt("11") //表示字符串"11"是10进制的数

   //注意了,radix是0、10均表示10进制的数,省略的时候进制可能是8、10、16
   var n=parseInt("11",0) //表示字符串"11"是10进制的数
   var n=parseInt("11",NaN) //表示字符串"11"是10进制的数
   var n=parseInt("11",10) //表示字符串"11"是10进制的数


   使用方法总结:
   1、看参数1是否是字符串,如果不是则先转成字符串(如果是非字符串类型,会发生隐式类型转换)
   2、先确定进制
   3、根据进制截取最终的字符串,如果最终是空字符串,则返回NaN
     (截取的规则是这样的,从字符串的首位(如果是0的8进制数,则从0之后开始截取,有点特殊;如果是0x的16进制数,则从0x之后开始截取,有点特殊)
     (如果是空格、+会忽略哦,如果是-则会输出)开始,依次向后截取,直到“非数字”或者“非指定进制范围内”的字符截止)
   4、转成10进制

   var num = parseInt(321, 0) //321
   var num = parseInt(321, NaN) //321
   var num = parseInt(321, 2) //NaN
   var num = parseInt("210", 3)//210
   var num = parseInt("329", 6)//20
   var num = parseInt("012", 0)//12
   var num = parseInt("0x12")//18
   var num = parseInt(parseInt,16)//15 这里为什么是15呢?因为parseInt是一个函数,其实这里的值是"function(){}"
   var num = parseInt(alert,16)//15
   var num = parseInt(console.log,16)//15
   var num = parseInt(0.000005)//0,直接使用“字面量”表示
   var num = parseInt(0.0000005)//5,这里返回5是因为,小数位后面长度长多6位时,采用科学基数法表示,即”5e-7“

  =====================================================================
  对于数值型而言,小数位前长度大于21或小数位后长度大于6时,均使用科学计数法表示
  =====================================================================



  执行过程分析:(第一个参数命名为参数1,第二个参数命名为参数2)
  -----------------------------------------------------
  1、查看参数1是否是字符串,如果不是,则会发生隐式类型转换
  2、确定基数(进制)
       a、有明确指定基数,则以指定的基数为准
       b、没有明确指定基数,则以参数1进行判断来确定基数,
          首先,参数1字符串是以“0”打头,则es5以前的版本中,基数为8,es5之后的版本中,基数为10
          其次,参数1字符串是以“0x"打头,则基数是16,
          最后,其他情况,基数是10
  3、以确定的基数来对参数1字符串进行有效性截取(非数字或基数范围外的均视为非法字符)
  4、如果截取的字符串是空字符串,“”则返回NaN
     如果是非空有效的字符串,则按照进制规则转换成10进制的数


     0 1 2 3 4 5 6 7 8 9  A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z
     0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35





[0/0] == NaN
Infinity/Infinity == NaN
0/NaN==NaN
NaN/0==NaN
0/Infinity == 0
Infinity/0 == Infinity

关于在JS中“{}”的使用特别说明

表示代码块

表示一个JS对象

经典特殊数据类型转换小结

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/107454.html

相关文章

  • 原生JS揭秘—撩开this面纱

    摘要:随着函数使用场景的不同,而发生变化。是当前执行上下文中的一部分。在中新增了该方法也是强制更改指向。但是和的区别是更改后不会立即执行,它会返回一个新函数。 this何意?在英文中this是一个人称代词,表示这个的,具体指哪个?不确定,只有在具体的语境中才可确定,在编程语言中this也有同样的类似特性。在js中this是一个关键字,它不能被当做变量、属性,也不可以进行赋值操作。this 随...

    Brenner 评论0 收藏0
  • 自上而下,逐步揭开PHP解析整数面纱

    摘要:而这个类型的最终之所以输出为,是因为进行科学计数法之后的精度丢失了,重新转成时就恢复不了原来的值。此类问题解决方案对于存储,超过最大表示范围的纯整数,在中可以使用保存,在查询出来的时候会将其使用类型保存的。 遇到的问题 最近遇到一个PHP大整数的问题,问题代码是这样的 $shopId = 17978812896666957068; var_dump($shopId); 上面的代码输出...

    qingshanli1988 评论0 收藏0
  • 剑指Kubernetes 揭秘腾讯云PaaS技术选型策略

    摘要:腾讯云在年底决定开发容器产品随后组建容器技术团队并进行技术选型通过对不同编排工具的分析对比最终选择作为容器编排引擎并且迅速在年初推出容器解决方案为用户提供托管的一站式服务。但是腾讯云最终选择了现在看来这个选择无比正确。Kubernetes 很火,一大批互联网公司早已领先一步,搭建起专有的 PaaS平台,传统企业们看到的 Kubernetes的趋势,亦不甘落后,在试水的道上一路狂奔。虽然,Ku...

    icattlecoder 评论0 收藏0
  • 揭开面纱 踏足云世界 再犹豫该OUT了

    摘要:一般流程你可以通过良好的选择一种构造来设计你自己的文件领域。 随着云世界的日新月异,想进入云世界的您在面对大量的选择时该何去何从?下面是一些关于知名云服务的使用和测试总结。当然在这之前,我们必须知道云是建立在托管您的应用程序上的服务。 Auto-Scalling — 当需求增加时,你可以自动的获得更多资源(一般情况下是更多的虚拟机)来响应请求。这在一般的应用程序中很少用到,但能保证你的服...

    Shimmer 评论0 收藏0
  • 揭开React中server-side rending神秘面纱

    摘要:与的兴起紧密相连。现在情况下,所有发送到端的请求都会被直接返回成。这样对于做的部门来说也是十分有利的。这个函数将会接受服务端渲染的代码并挂载事件处理函数。用于在渲染的过程中追踪可能的重定向请求比如需要根据响应重定向。 原文地址:https://medium.freecodecamp.o... showImg(https://segmentfault.com/img/remote/14...

    0x584a 评论0 收藏0

发表评论

0条评论

Moxmi

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<