JavaScript类型转换的迷糊事儿

最近在写公司的登陆注册模块,遇到类型不一样相比较的时候,就心惊胆战,每次都要用浏览器来验证一下,决定乱七八糟的随便写一下,方便往后本身回顾知识~正则表达式

弱类型带来的那些让人迷糊的事

弱类型带来的好处之一:终于不用本身肯定数据类型了。数组

写C++这类的强类型语言,每次都要先肯定是intchar仍是string之类的,可是仅仅经过var,怎么解决工做过程当中的不一样数据类型的比较问题的呢?浏览器

这个问题烦了我好久,当初学js的时候就只能记住最简单的其余类型到boolean的转换,涉及到其余的,只能晕菜。。。函数

下面分几步来简单的探探不一样类型的转换吧~性能

如下的内容,均可以从《JavaScript权威指南》中找到。学习

其余值转换成boolean

在编写JavaScript代码的过程当中,几乎不用考虑它的取值类型。在工做过程当中,咱们有可能会须要在if的条件判断中对参数进行判断,这就涉及到了boolean值的转换。spa

当JavaScript指望使用一个布尔值的时候,你能够提供任意类型值,JavaScript将根据须要自行转换类型,一些值(真值)转为true,其余值(假值)转为false--《JavaScript权威指南》(page 48)prototype

对于布尔值类型的转换,实际上只须要特别记住几个特殊的会转换成false的值就能够了3d

这些值包括:undefinednullfalse""0-0NaNcode

全部的其余值(包括全部对象)都会转换成true

通常在工做中,咱们能够直接使用:

if (value){
    ...
}

根据js的语言特性,可让浏览器直接替咱们判断,省时省力,我我的不太喜欢下面的写法:

if (value == null){
    ...
}

尽管这样也能够达成目标,可是总感受多敲了代码,还须要特别注意若是不是null或者undefined,但也是假值的状况。

须要特别注意:假值中包含0 or -0的状况

还有一个小点须要特别注意一下:jQuery中选择符选择某个DOM节点,也许这个DOM节点并不存在,可是$(selector)返回的值是一个对象,因此,咱们判断是否存在这个DOM,须要经过$(selector).length > 0来判断是否存在。

原始值转换成字符串

原始值:数字字符串布尔值nullundefined

原始值转换成字符串的状况估计是最简单的了,能够直接理解成在原始值的两边加上""就好了

undefined --> "undefined"
null      --> "null"
true      --> "true"
false     --> "false"
0         --> "0"
-0        --> "-0"
NaN       --> "NaN"
Infinity  --> "Infinity"
-Infinity --> "-Infinity"
1         --> "1"
......

原始值转换成数字

除了字符串,大部分原始值都会有固定的转换结果,以下:

undefined  --> NaN
null       --> 0
true       --> 1
false      --> 0

可是,字符串的转换有点微妙,给个人感受有点相似Number()方法,可是注意,只是相似,调用Number()会生成包装对象,而不是一个数字。

字符串转换成数字,会有如下的特色:

  1. 以数字表示的字符串能够直接转换成数字

  2. 容许字符串开头跟结尾带有空格

  3. 在开始和结尾处的任意非空格符都不会被当成数字直接量的一部分,转换结果变成NaN

结果以下:

"one"  --> NaN
"u123" --> NaN
" 123" --> 123
"123 " --> 123
" 12 " --> 12

原始值转换成对象

原理:原始值经过调用String()Number()Boolean()构造函数,转换成他们各自的包装对象

存取字符串、数字或者布尔值的属性的时候建立的临时对象叫作包装对象,他只是偶尔用来区分字符串值和字符串对象、数字和数值对象以及布尔值布尔对象。一般,包装对象只是被看作是一种实现细节,而不用特别关注。--《JavaScript权威指南》(page46)

可是nullundefined信仰比较坚决,就是不想转成对象,从而,当将它们用在指望是一个对象的地方都会抛出一个错误throws TypeError

注意:只是在转换的过程当中会抛出Error,在显性建立对象的时候,不会报错
new Object

对象转换成原始值

对象转换成原始值,能够分红如下三种:

  1. 对象转换成boolean

  2. 对象转换成字符串(object-to-string)

  3. 对象转换成数字(object-to-number)

其中,对象转换成boolean,规则很是简单:全部的对象都转换成true(包括包装对象)

注意new Boolean(false)是一个对象,转换成布尔值也是true

而对象转换成字符串以及对象转换成数字根据场景不一样,有些复杂,在学习了解他们的转换过程以前,先来看两个函数:toString()以及valueOf()

一、在MDN中搜索toString,你会发现以下情形:
toString

若是细细查看,你会发现:全部的对象都有toString()方法,做用就是返回一个反映这个对象的字符串。

可是,这个方法返回的值有些时候不是那么的好。

例如:Object.prototypr.toString()

默认状况下,每一个对象都会从Object上继承到toString()方法,若是这个方法没有被这个对象自身或者更接近的上层原型上的同名方法覆盖(遮蔽),则调用该对象的toString()方法时会返回"[object type]",这里的字符串type表示了一个对象类型。

例如:

var o = new Object();
o.toString()    //返回[object Object]

不少类定义了不少特定版本的toString()方法:

  1. 数组类Array.prototype.toString()

  2. 函数类Function.prototype.toString()

  3. 日期类Date.prototype.toString()

  4. 正则类RegExp.prototype.toString()
    ······
    使用方法及返回结果以下:
    objecttoString

二、在MDN搜索valueOf,能够获得与toString类似的结果。

可是,这个方法的任务并无详细的定义,我甚至没法从MDN的描述中得出它与toString的区别。

JavaScript calls the valueOf method to convert an object to a primitive value. You rarely need to invoke the valueOf method yourself; JavaScript automatically invokes it when encountering an object where a primitive value is expected.

也许从下面的代码中咱们能够初窥一二:

[1,2,3].toString() // --> "1,2,3"
[1,2,3].valueOf() // --> [1, 2, 3]
(function(x){f(x);}).toString() // --> "function (x){f(x);}"
(function(x){f(x);}).valueOf() // --> function anonymous(x)
/\d+/g.toString() // -->"/\d+/g"
/\d+/g.valueOf() // --> /\d+/g
new Date(2010,0,1).toString() // --> "Fri Jan 01 2010 00:00:00 GMT+0800 (中国标准时间)"
new Date(2010,0,1).valueOf() // --> 1262275200000

根据上面的结果,能够尝试得出如下的结论:

对象是复合值,并且大多数对象没法真正表示为一个原始值,所以默认的`valueOf()`方法简单地返回对象自己,而不是返回一个原始值

数组、函数以及正则表达式简单地继承了这个默认的方法,而日期类定义的valueOf()方法返回它的一个内部表示:1970年1月1日以来的毫秒数

有了上面的两个方法,咱们就能够进行对象到字符串以及对象到数字的转换了。

对象到字符串的转换的步骤以下:

  1. 若是对象具备toString()方法,那么就调用这个方法,返回一个原始值,若是这个值自己不是字符串,JavaScript会将其转换成字符串,并返回字符串的结果。

  2. 若是没有toString()方法,或者这个方法不返回一个原始值,那么调用valueOf()方法,返回一个原始值,若是这个值自己不是字符串,JavaScript会将其转换成字符串,并返回字符串的结果。

  3. 不然JavaScript没法从toString()或者valueOf()得到一个原始值,这时抛出一个类型错误。

对象到数字的转换的步骤以下:

    1. 若是对象具备valueOf()方法,那么就调用这个方法,返回一个原始值,若是这个值自己不是字符串,JavaScript会将其转换成字符串,并返回字符串的结果。

  1. 若是没有valueOf()方法,或者这个方法不返回一个原始值,那么调用toString()方法,返回一个原始值,若是这个值自己不是字符串,JavaScript会将其转换成字符串,并返回字符串的结果。

  2. 不然JavaScript没法从toString()或者valueOf()得到一个原始值,这时抛出一个类型错误。

结束了?你还没考虑应用呢!

因为JavaScript是弱类型语言,因此咱们对于类型转换的应用其实有许多。

例如:if判断、+运算符以及==运算符等等

关于+

  1. 进行数字加法以及字符串链接操做

  2. 若是其中的一个操做数是对象,则将对象转换成原始值

==也是js判断中经常使用的涉及到类型转换的一个运算符
关于==

  1. 若是两个值类型相同,进行===比较

  2. 若是两个值类型不一样,他们可能相等,须要按照必定的规则来进行类型转换并比较

==类型不一样时的转换规则:

  1. 若是一个值是null,另外一个值是undefined,则相等

  2. 若是一个是字符串,另外一个值是数字,则把字符串转换成数字,进行比较

  3. 若是任意值是true,则把true转换成1再进行比较;若是任意值是false,则把false转换成0再进行比较

  4. 若是一个是对象,另外一个是数值字符串,把对象转换成基础类型的值再比较。对象转换成基础类型,利用它的toString或者valueOf方法。 js核心内置类,会尝试valueOf先于toString能够理解为对象优先转换成数字);例外的是DateDate利用的是toString转换。非js核心的对象,经过本身的实现中定义的方法转换成原始值

关于比较运算符<|>|<=|>=

  1. 若是操做数为对象,那么这个对象将转换成原始值:若是valueof()返回一个原始值,那么直接使用这个原始值。不然,使用toString()的转换结果进行比较操做

  2. 在对象转换成原始值以后,若是两个操做数都是字符串,那么将按照字母表的顺序对两个字符串进行比较,字母表的顺序是指组成这个字符串的16位unicode字符的索引顺序。注意:字符串比较是区分大小写的,全部大写的ASCII字母都小于全部小写的ASCII字母

  3. 在对象转换成原始值以后,若是至少有一个操做数不是字符串,那么两个操做数都将转换成数字进行数值比较。0-0是相等的。Infinity比其余任何数字都大(除了Infinity自己),-Infinity比其余任何数字都要小(除了它自己)。若是其中一个操做数是(或转换后是)NaN,那么比较操做符老是返回false

加号运算符与比较运算符的区别

  1. 加法运算符更偏心字符串的操做,比较运算符更偏心数字

  2. 只有两个操做数都是字符串,才进行字符串的比较

1+2 //加法,结果是3
"1"+"2" //字符串链接,结果是"12"
"1"+2  //字符串链接,结果是"12"
11 < 2 //数字的比较,结果是false
"11" < "3" //字符串比较,结果为true
"11" < 3 // 数字比较,"11"转换成11,结果为false
"one" < 3 //数字的比较,"one"转换成NaN,结果为false

注意:<=以及>=在判断相等的状况的时候,并不依赖相等或者严格相等运算符的比较规则,它们只是简单的不大于不小于

反思

昨天公司的一件事对个人触动挺大的,公司里面的两个后台为了表单提交是用GET仍是POST争吵了半个小时。有些时候,不经意就会忽略一些问题,好比代码的质量,性能的提升,这些都是值得程序猿们深刻探究的问题。

记得有过这样一句话“你对待技术的态度,就是你对待生命的态度”。

做为一名小猿,继续奋斗去喽~

相关文章
相关标签/搜索