前端面试问题详解

78 阅读4分钟

js 部分

1. 0.1 + 0.2 !== 0.3

js 内部,所有数字都是以64位浮点数形式储存,即使整数也是如此。所以,11.0是相同的,是同一个数

js计算时,会将十进制转换成二进制

   通过`toString(进制位数)`,可对数值进行相应进制的转换。
   如(0.1).toString(2),  // 0.1转换为二进制为'0.0001100110011001100110011001100110011001100110011001101' 
    实际是0.000110011001100...(循环)
   (0.2).toString(2),  // 0.2转换为二进制为'0.001100110011001100110011001100110011001100110011001101'

为什么精度会产生呢?

首先0.1这种转化为二进制码是有误差的,尾数是一个不断循环的数,但是浮点数的尾数是有限的,所以需要省略一部分,这就产生了一部分误差

其次,在浮点数加法运算里面,有对阶操作。対阶会损失一部分尾数,如果尾数后面都是0(整数或者0.5之类的),没影响。但是如果是0.1转换成的二进制浮点数码的尾数,対阶的时候舍弃部分尾数明显也会造成误差。

我们从上面的浮点数二进制码可以看出一个规律,

如果是整数,尾数都是0
如果是小数,如果是0.5、 0.25、 0.125这种的,尾数都是0
如果是0.1,0.2,0.4这种的小数,尾数都是无限循环的

  > [面试必备之详解JS数字精度](https://segmentfault.com/a/1190000021684144) \
[toPrecision使用](https://www.runoob.com/jsref/jsref-toprecision.html)
2. Map类型与WeakMap类型的区别,Map与Object类型的区别?
`new Map(传入一个可迭代的对象)`

 a). Map类型可对Map实例的entries()进行iterator遍历, 且其键值可以是任意类型。
 
 b). WeakMap类型实例,其键值只能是对象,且不能对WeakMap实例.entries()进行遍历。 

 c). 通过查看其prototype对象,没有Symbol(Symbol.iterator)方法

 d). Object的键值只能是字符串类型,如果是其它,如果可转为字符串,会更改其键值为字符串
3. 数值的toFixed(2)四舍五入准确吗?如何准确?
`不确定准确`,因为对于如1.005类似的数值转换
如:`1.005.toFixed(2)`返回的是`1.00`而不是`1.01`。

原因:`1.005`实际对应的数字是`1.00499999999999989`,在四舍五入时全部被舍去!

`不过(1.005).toPrecision(4) ===> 1.005`

**怎么解决这个问题呢,方法如下:**

```
if (!Number.prototype._toFixed) {
    Number.prototype._toFixed = Number.prototype.toFixed;
}
Number.prototype.toFixed = function(n) {
    return (this + 3e-16)._toFixed(n);
};

//加上一个非常非常小的数,此时就正常了
1.005.toFixed(2)
"1.01"
```
4. 如何实现数值每三位逗号分隔?
const c = 123456789;
const reg = /(\d)(?=(?:\d{3})+$)/g;
const newNumber = c.toString().replace(reg,'$1,');
5. undefined 与 null 有什么区别?

a. undefined 表示此处该有值,但是缺省了。 null 表示没有对象,此处不该有值、

b. Number(undefined) 为NAN , Number(null) 为0

c. null作为对象原型链的终点, undefined作为对象未定义属性的默认值

d. typeof null 为object, typeof undefined 为undefined

>>> 点击此处查看为什么typeof null为object?

原理是这样的,不同的对象在底层都表示为二进制,在 JavaScript 中二进制前三位都为 0 的话会被判断为 object 类型, null 的二进制表示是全 0,自然前三位也是 0,所以执行 typeof 时会返回“ object ”。

这个bug是第一版Javascript留下来的。在这个版本,数值是以32字节存储的,由标志位(1~3个字节)和数值组成。标志位存储的是低位的数据。

这里有五种标志位:
(1) 000:对象,数据是对象的应用。
(2) 1:整型,数据是31位带符号整数。
(3) 010:双精度类型,数据是双精度数字。
(4) 100:字符串,数据是字符串。
(5) 110:布尔类型,数据是布尔值。
6. 检测类型的方法有哪些?

a. typeof 判断基础类型

b. instanceof 判断对象类型可用,对基础类型不可用

    [] instanceof Array --> true
    'zzz' instanceof String --> false

c. constructor 检测实例与类的关系

  'zzz'.constructor === String ---> true
  ({}).constructor === Object  ---> true

d. `Object.prototype.toString'

  Object.prototype.toString.call([]) ----> '[object Array]'
  
7. instanceof的原理
8. 判断是否为数组的方法?
```
const arr = []
1) Object.prototype.toString.call(arr).indexOf('Array') > -1
2) arr.__proto__ === Array.prototype
3) Array.isArray(arr)
4) arr instanceof Array
5) Array.prototype.isPrototypeOf(arr)

```
9. 浏览器跨标签页通信的方式都有什么?

vue部分

  1. vue2, vue3 如何实现响应式?
  2. vue中nextTick如何触发?
  3. vue如何收集依赖?
  4. vue如何diff?
  5. 为什么使用虚拟dom?

网络部分

  1. 0.0.0.0与127.0.0.1的区别 文章1 文章2

浏览器部分

  1. 第三方Cookie指的是什么? 如何阻止第三方Cookie ?

    • 使用隐藏域来存储cookie。
    • 设置HTTPOnly属性,禁止浏览器通过JavaScript读取cookie1。
    • 设置SameSite属性,限制浏览器将cookie发送到第三方网站1。
    • 在浏览器设置中,选择阻止第三方cookie和网站数据2。

    此外,还可以通过安装浏览器插件、使用加密连接等方式来增强cookie的安全性,防止被第三方网站读取