js--类型转换

写在前面的话

近期刷了点js的面试题,发现很多基础知识已经模糊,于是重新回去看了一下《javascript权威指南(第六版)》,现将薄弱知识点记录下来,供以后再次复习。

正文开始

首先祭出必备的万能神器——类型转换表格(显式转换):

显式转换表格.png
图中一些知识点的解释:
  • 首先关于null、undefined转换为Object,在权威指南中写的是TypeError,但这里其实用Object()来转换时,会返回一个空对象{},报错的情况是在当你把它们当做一个对象来用时,比如读取对象属性null.x,此时就会出现TypeError。
    • 补充:同样会报错的还有把一个非函数对象拿来调用
    • 补充:虽然null不能当作对象来用,但是要记住 typeof null 的值是 object
  • 字符串转换为数字时调用的是Number(),该函数只能转换纯数字字符串,允许前后有空格,中间不能有,否则返回NaN。
  • 补充:parseInt()、parseFloat()同样可以将字符串转换为数字,不同于Number()的是,只要非空格的第一个字符是数字,它们就会尽可能长地进行转换,直到遇到空格会或非字母。如果第一个非空格字符是字母,则返回NaN。
  • 对于数组[9]转化为Number()时的情况,还可以扩展到[[[9]]]转化为number时,也为9.

一些前置知识点

不同类型的对象调用toString()的结果(在没有重写该方法的情况下):
  • 普通对象{}.toString() => "[object Object]"
  • 数组类.toString() => 将每个数组元素转化为一个字符串,并在元素之间添加逗号后,合并成一个字符串【相当于arr.join(","))】
  • 函数类.toString() => 返回这个函数的实现的字符串【也就是定义函数的源代码"function(){...} "】
  • 日期类(Date).toString() => 返回一个可读的日期,与console.log结果相同
  • RegExp类.toString() => 返回该正则表达式的字面量形式的字符串【相当于定义时的源字符串】
不同类型的对象调用valueOf()的结果(在没有重写该方法的情况下):
  • 各种对象调用valueOf()时的结果,普通对象、数组类、函数类、RegExp类,都是返回他们本身。
  • 如:Object {a: 1, b: 4} 、 function(){} 、 ["a", "b", "c"] 等形式。
  • 注意这里与toString()不同,并不会用双引号括起来,toSting()的结果用typeof是string,而这里的结果用typeof是object、function等
  • 日期类.valueOf()比较特殊,会返回一个1970年1月1日以来的毫秒数。

toString()和valueOf()在一些情况下需要替代使用:

对象转化为字符串的步骤:
  • 如果具有toString(),且可以返回一个原始值,则调用,再将该原始值转化为字符串。
  • 否则(没有toString()或不返回原始值),调用能返回原始值的valueOf(),再将这个原始值转化为字符串。
  • 否则以上两个方法都不能取得原始值,返回一个类型错误
对象转化为数字的步骤:
  • 先调用能够返回原始值的valueOf(),将原始值转换为数字。
  • 否则调用toString()得到原始值,转化为数字。
  • 上述两个方法都不能取得原始值,就返回一个类型错误。
下面来说说隐式类型转换
一元运算符部分
  • 遇到 - * / % 等4个运算符时,会把操作数转化为数字。
  • 遇到!时,会把操作数转化成Boolean值,并取反。
  • 遇到+号时,比较复杂:
    • 如果其中一个操作数是对象,则遵循对象到原始值的转换规则,除了日期对象调用toString(),以外,其他对象都通过valueOf()来转换(这是+号的隐式规定,即使另一个操作数是字符串,也不会优先调用toString())。当然这里调用valueOf()的前提是它可以返回一个原始值,如果没有这个方法或者不返回原始值,则调用toString()。
  • 如果是布尔值和字符串,布尔值转化为字符串,拼接。
  • 如果是布尔值和数字,布尔值转化为数字,相加。
  • 如果是数字和字符串,则进行拼接处理。
  • 如果是两个数字,加法操作。
  • 下面举几个栗子:
    • x + "" 等价于String(x)
    • +x 等价于Number(x)
    • x-0 等价于Number(x)
    • !!x 等价于Boolean(x)
比较运算符部分
  • == 的比较过程:

  • null == undefined,为true

  • 数字vs字符串,字符串转化为数字

  • 布尔值vs字符串,两者转数字

  • 字符串vs字符串,按unicode依次比较,直到结束或某一个字符不相同

  • 对象vs数字,对象vs字符串,对象首先尝试valueOf(),再尝试toString()【日期类只调用toString()】,目的都是将对象转化为原始值,再进行比较。

  • 如果其中一个操作数是NaN,那么总是返回false

  • 其他不同类型之间的比较均不相等

  • . > < >= <=等比较运算符

  • 如果有操作数是对象,则按==中的方式转换为原始值。

  • 转换之后如果两者都是字符串,则按照Unicode字符的索引顺序比较

  • 如果转换后至少有一个操作数不是字符串,则两个操作数都转化为数字进行比较。

  • 如果其中一个操作数是NaN,那么总是返回false

说到NaN,再补充一点
  • 用isNaN来检测某个值是否为NaN其实不准确,因为isNaN({})等在判断之前,首先会用Number()将{}进行一次隐式转换,任何对象、非纯数字的字符串,都会被转化成NaN,此时判断时会得true
  • 真正检测NaN值的,是利用它不等于自身的性质,a !== a 来检测,如果为true,则a是NaN。
举个综合的例子:
  • console.log(([])?true:false);
  • 解析:判断[]的真假,Boolean([])是true,所以控制台输出true。
  • console.log(([]==false?true:false));
  • 解析:判断[]是否等于false,不能简单得看表格里的Boolean()转换的值,而是要遵循==的转换规则,==两边只要有一个不是字符串, 就要将两边都转换成数字再来比较,根据表格,[]转为number值时是0,false转为number值也是0,转换后是 0==0?,成立,所以控制台输出true。
  • console.log(({}==false)?true:false);
  • 解析:{}转为number值总是NaN,false转换成数字是0,最终NaN == 0 ?,不成立,所以控制台输出false。

最终总结

  • 对象的隐式转换里面坑比较多,其中之一就是,基础知识不牢固的话,不知道该转换成什么类型。这里根据自己的理解记录一下:
  • 在if中,需要布尔值,所以总是调用Boolean()来进行转换。
  • 在==、><、>=、<=这些比较运算符中,默认要求是要转换为Number。对象优先调用valueOf(),其次调用toString(),最终要取得一个原始值(否则报错),然后再根据两边的原始值判断是否需要进一步转换成数字。
  • 补充:除了两边的原始值都是字符串的情况,否则都需要进一步转换成数字来比较。
  • 在switch中,switch里的变量与case值比较时,是===,既毕竟类型,也比较值。

今天的笔记暂时到这,如果有不对的地方,欢迎大家指正交流 : )

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 很久之前,看到过这样一种判断 当时觉得很神奇,翻了些博客,但也似懂非懂。今天翻看博客的时候,偶然又看见了它,感觉跟...
    ebfc7d0362e4阅读 610评论 0 5
  • 有一道面试题是: 实现一个函数,运算结果可以满足如下预期结果:add(1)(2) //3add(1,2,3)(10...
    Wonder233阅读 221评论 0 0
  • 强制转换 强制转换主要指使用Number、String和Boolean三个构造函数,手动将各种类型的值,转换成数字...
    灯火阑珊Zone阅读 390评论 0 3
  • 2016.12.4 今天 响铃22岁 时间真的是一个神奇的鬼 还清楚的记得5年前的17岁,长大,好像只是在那一瞬间...
    _湫子阅读 299评论 0 0
  • 文/沐沐先森 “其实我并不是一个特别好的人。”沐同学总是这样说。 尤其是,今天和父母(其实沐同学更愿意以比较熟悉的...
    沐沐先森阅读 382评论 2 2