** 写在前边**
第一次去面试,面试官问我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 的使用
1// 通常参数是字符串类型,如果为对象类型,就会调用 toString 方法
2let s1 = Symbol(参数);// 这个参数可以认为是 Symbol 实例的一个描述,用于区分
3
4// 第一种写法
5let a = {};
6a[s1] = 'Hello!';
7
8// 第二种写法
9let a = {
10 [s1] = 'Hello';
11}
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 基础的知识点,虽然这些知识点比较坑,也比较杂,但是通过整理清晰了很多,文章中可能讲的地方有问题,可以给小鹿指出。
这些不但是基础,更是面试中最高频面试官常常问到了,不同的公司面试官的问法也是大不相同,所以换汤不换药,上边总结的知识点也存在很多不足的地方,欢迎各位大佬补充。