动画:面试官问我 0.1 + 0.2 __ 0.3 ? 为什么?该如何正确回答?

7,710 阅读6分钟

写在前边

第一次去面试,面试官问我0.1 + 0,2 __ 0.3?估计很多人都知道在 JS 中0.1 + 0.2 != 0.3 的,至于大于还是小于还真没弄明白。

像这种变态的问题,在 JS 中存在很多,那小鹿就干脆整理成了一系列,希望对你的 JS 基础进一步加牢,也希望你能在面试中顺利拿到 offer。

1、学习困惑

我先谈谈我自己之前在方面遇到的困惑,学习 JS 很多基础的知识起初不是那么顺利的,尤其是刚接触 JS 的时候,因为 JS 历史遗留了一些 bug,再加上它是弱类型语言,不像其它面向对象强类型语言很多概念一样清晰。

2、学习建议

不建议在刚接触就深入学习,很多知识知道这么回事就可以,比如null为什么通过 typeof 检测为对象类型,一开始你只知道他通过 typeof 检测为对象类型就可以。什么时候去理解这些知识点的原理?

如果你觉得自己很懒,那就先不要去学习了,如果你对它的原理感兴趣,自然而然你就学会探索了。但是,到了面试的时候,当面试官问到你这块问题的时候,会递归式的问你了,到时候,你不得不去学原理了,这是你会发现,这些原理性的东西零散,这个人说东,那个人说西,然后我就根据优质的文章自己学习了下,整理成了一系列。

思维导图

1、基本类型分类

JS 的基本类型分为两大类型,分别为原始类型和对象类型。

原始类型包括哪些?对象类型包括哪些?为什么要这样分类?他们的区别又是什么?

原始类型存储的都是值,而对象类型存储的都是地址。如下图:

如上图所示,我们清楚了原始类型和对象类型最根本的区别,那么问题又来了,当我们进行变量之间赋值的时候,原始类型直接赋值的是值,而对象类型赋值的是地址。

所以,当我们将对象作为参数进行传递的时候,在函数内改变的是该地址指向的对象,而传递的参数是原始类型,则改变的是一个副本(复制的另一个值)。也就是说,如果是对象,则改变了原始的值,而不能改变原始类型原始的值。

原始类型共六种,分别为String、Number、Boolean、null、undefined、symbol

接下来对这六种原始类型中存在的问题我们逐一解决。

2、null

对于null有一个历史存留的 bug,null是对象类型吗?虽然我们使用 typeof 检测null是对象类型,这其实是一个 bug。

2.1 原因是什么?

因为 JS 最初的版本是 32 位系统的,为了将性能将用低位存储变量类型信息,000 开头表示代表的是对象,此时null表示全零,所以系统就错误的将null判断为对象类型。虽然 JS 内部判断代码已经更改,但是这个 bug 一直留存下来。

2.2 null 出现的情况汇总

1、手动设置变量的值或者对象某一个属性值为null(此时不赋值,后边会赋值)。

2、在 JS 的 DOM 元素获取中,如果没有获取到指定的元素对象,结果一般都是null。

3、Object.prototype._proto_的值也是null。

4、正则捕获的时候,如果没有获取到结果,默认的也是null。

3、symbol

有关symbol使用的比较少,但是它的存在是有原因的。

3.1 symbol 是什么?

symbol表示独一无二的值,因为由于对象的属性都是字符串类型,我们避免不了相同字符串冲突的问题。所以为了防止对象的属性都是字符串类型而冲突引入的。

3.2 symbol 的使用

 // 通常参数是字符串类型,如果为对象类型,就会调用 toString 方法
 let s1 = Symbol(参数);// 这个参数可以认为是 Symbol 实例的一个描述,用于区分
 
 // 第一种写法
 let a = {};
 a[s1] = 'Hello!';
 
 // 第二种写法
 let a = {
    [s1] = 'Hello';
}

4、undefined

4.1 undefined 出现的情况?

1、变量提升: 只声明未定义默认值就是undefined。

2、严格模式下:没有明确的执行主体,this就是undefined。

3、对象没有这个属性名,属性值是undefined。

4、函数定义形参不传值,默认就是undefined。

5、函数没有返回值(没有return或者return;),默认返回的就是 undefined。

5、为什么 0.1 + 0.2 != 0.3 ?

上边我们讲了一些有关数据类型的坑,我们回过头来,0.1 + 0.2 __ 0.3呢?为什么会出现不相等的情况呢?面试该如何回答面试官?

5.1 是什么导致了这种情况?

原因很简单,JS 采用的是双精度版本,这个版本就存在精度问题,就导致了上边这种情况。

5.2 内部的原理是什么?

我们计算机的信息全部转化为二进制进行存储的,那么0.1的二进制表示的是一个无限循环小数,该版本的 JS 采用的是浮点数标准需要对这种无限循环的二进制进行截取,从而导致了精度丢失,造成了0.1不再是0.1,截取之后0.1变成了 0.100...001,0.2变成了0.200...002。所以两者相加的数大于0.3。

那好,既然0.1不等于0.1了,那为什么我在控制台上输出console.log(0.1)还等于0.1呢?

因为在输入内容进行转换的时候,二进制转换成十进制,然后十进制转换成字符串,在这个转换的过程中发生了取近似值,所以打印出来的是一个近似值。

如果你把上边的原理和面试官一说,卧槽,面试官不给你 offer 都难,哈哈,开个玩笑,拿到 offer 不仅靠基础,也要靠你的其他综合能力。

小结

今天我们主要总结了一下有关 JS 基础的知识点,虽然这些知识点比较坑,也比较杂,但是通过整理清晰了很多,文章中可能讲的地方有问题,可以给小鹿指出。

这些不但是基础,更是面试中最高频面试官常常问到了,不同的公司面试官的问法也是大不相同,所以换汤不换药,上边总结的知识点也存在很多不足的地方,欢迎各位大佬补充。


❤️ 不要忘记留下你学习的脚印 [点赞 + 收藏 + 评论]

文章都看完了,为何不妨点个赞呢?嘻嘻,那就说明你很自私,你怕那么好的文章让别人也看到。开个小小玩笑。

其实我也很自私,我把我的一直以来坚持原创的公众号:「小鹿动画学编程」偷偷给你,里边汇聚了小鹿以动画形式讲解的数据结构与算法、网络原理、Web 等技术文章。

作者Info:

【作者】:小鹿

【原创公众号】小鹿动画学编程

【简介】:和小鹿同学一起用动画的方式从零基础学编程,将Web前端领域、数据结构与算法、网络原理等通俗易懂的呈献给小伙伴。公众号回复 “资料” 送一从零自学资料大礼包!

【转载说明】:转载请说明出处,谢谢合作!~