前端面试题(基础篇十)

发布于:2024-06-27 ⋅ 阅读:(142) ⋅ 点赞:(0)

一、JavaScript内置类型

JS 中分为七种内置类型,七种内置类型⼜分为两⼤类型:基本类型和对象 ( Object )。

基本类型有六种: null undefined boolea n, number string symbol

其中 JS 的数字类型是浮点类型的,没有整型。并且浮点类型基于 IEEE 754 标准实 现,在使⽤中会遇到某些 Bug。 NaN(not a number) 也属于 number 类型,并且 NaN 不等于⾃身。

对于基本类型来说,如果使⽤字⾯量的⽅式,那么这个变量只是个字⾯量,只有在必要的 时候才会转换为对应的类型。

let a = 111 // 这只是字⾯量,不是 number 类型
a.toString() // 使⽤时候才会转换为对象类型

对象( Object )是引⽤类型,在使⽤过程中会遇到浅拷⻉和深拷⻉的问题

let a = { name: 'FE' }
let b = a
b.name = 'EF'
console.log(a.name) // EF

二、深浅拷贝

letet a a = {
 age : 1
}
let b = a
a.age = 2
console.log(b.age) // 2

从上述例⼦中我们可以发现,如果给⼀个变量赋值⼀个对象,那么两者的值会是同⼀个引 ⽤,其中⼀⽅改变,另⼀⽅也会相应改变。

通常在开发中我们不希望出现这样的问题,我们可以使⽤浅拷⻉来解决这个问题

浅拷贝

⾸先可以通过 Object.assign 来解决这个问题

let a = {
 age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1

当然我们也可以通过展开运算符 来解决

let a = {
 age: 1
}
let b = {...a}
a.age = 2
console.log(b.age) // 1
通常浅拷⻉就能解决⼤部分问题了,但是当我们遇到如下情况就需要使⽤到深
拷⻉了
let a = {
 age: 1,
 jobs: {
 first: 'FE'
 }
}
let b = {...a}
a.jobs.first = 'native'
console.log(b.jobs.first) // native
浅拷⻉只解决了第⼀层的问题,如果接下去的值中还有对象的话,那么就⼜回
到刚开始的话题了,两者享有相同的引⽤。要解决这个问题,我们需要引⼊深

深拷贝

这个问题通常可以通过 JSON.parse(JSON.stringify(object)) 来解决
let a = {
 age: 1,
 jobs: {
 first: 'FE'
 }
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'native'
console.log(b.jobs.first) // FE

但是该⽅法也是有局限性的:

会忽略 undefined

不能序列化函数

不能解决循环引⽤的对象

let obj = {
 a: 1,
 b: {
 c: 2,
 d: 3,
 },
}
obj.c = obj.b
obj.e = obj.a
obj.b.c = obj.c
obj.b.d = obj.b
obj.b.e = obj.b.c
let newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj)

如果你有这么⼀个循环引⽤对象,你会发现你不能通过该⽅法深拷⻉

在遇到函数或者 undefined 的时候,该对象也不能正常的序列化

let a = {
 age: undefined,
 jobs: function() {},
 name: 'poetries'
}
let b = JSON.parse(JSON.stringify(a))
console.log(b) // {name: "poetries"}
你会发现在上述情况中,该⽅法会忽略掉函数和`undefined。
但是在通常情况下,复杂数据都是可以序列化的,所以这个函数可以解决⼤部分问题,并
且该函数是内置函数中处理深拷⻉性能最快的。当然如果你的数据中含有以上三种情况下,可以使⽤ lodash 的深拷⻉函数。

三、跨域

因为浏览器出于安全考虑,有同源策略。也就是说,如果协议、域名或者端⼝
有⼀个不同就是跨域, Ajax 请求会失败

跨域的解决方式

JSONP

JSONP 的原理很简单,就是利⽤ <script> 标签没有跨域限制的漏洞。通
<script> 标签指向⼀个需要访问的地址并提供⼀个回调函数来接收数据
当需要通讯时
<script src="http://domain/api?param1=a&param2=b&callback=jsonp"></script>
<script>
 function jsonp(data) {
 console.log(data)
}
</script>

JSONP 使⽤简单且兼容性不错,但是只限于 get 请求

CORS

CORS 需要浏览器和后端同时⽀持
浏览器会⾃动进⾏ CORS 通信,实现 CORS 通信的关键是后端。只要后端实现了 CORS ,就实现了跨域。
服务端设置 Access-Control-Allow-Origin 就可以开启 CORS 。 该属性表示哪些域名 可以访问资源,如果设置通配符则表示所有⽹站都可以访问资源

document.domain

该⽅式只能⽤于⼆级域名相同的情况下,⽐如 a.test.com b.test.com 适⽤于该⽅
只需要给⻚⾯添加 document.domain = 'test.com' 表示⼆级域名都相同就可以实现跨

postMessage

这种⽅式通常⽤于获取嵌⼊⻚⾯中的第三⽅⻚⾯数据。⼀个⻚⾯发送消息,另
⼀个⻚⾯判断来源并接收消息
// 发送消息端
window.parent.postMessage('message', 'http://blog.poetries.com');
// 接收消息端
var mc = new MessageChannel();
mc.addEventListener('message', (event) => {
 var origin = event.origin || event.originalEvent.origin;
 if (origin === 'http://blog.poetries.com') {
 console.log('验证通过')
 }
});

四、渲染机制

浏览器的渲染机制⼀般分为以下⼏个步骤

处理 HTML 并构建 DOM 树。

处理 CSS 构建 CSSOM 树。

DOM CSSOM 合并成⼀个渲染树。

根据渲染树来布局,计算每个节点的位置。

调⽤ GPU 绘制,合成图层,显示在屏幕上

在构建 CSSOM 树时,会阻塞渲染,直⾄ CSSOM 树构建完成。并且构建 CSSOM 树是⼀
个⼗分消耗性能的过程,所以应该尽量保证层级扁平,减少过度层叠,越是具体的 CSS 选
择器,执⾏速度越慢
当 HTML 解析到 script 标签时,会暂停构建 DOM,完成后才会从暂停的地⽅重新开始。
也就是说,如果你想⾸屏渲染的越快,就越不应该在⾸屏就加载 JS ⽂件。并且 CSS 也会
影响 JS 的执⾏,只有当解析完样式表才会执⾏ JS,所以也可以认为这种情况下,CSS 也
会暂停构建 DOM

图层

⼀般来说,可以把普通⽂档流看成⼀个图层。特定的属性可以⽣成⼀个新的图
层。不同的图层渲染互不影响,所以对于某些频繁需要渲染的建议单独⽣成⼀
个新图层,提⾼性能。但也不能⽣成过多的图层,会引起反作⽤
通过以下⼏个常⽤属性可以⽣成新图层
3D 变换: translate3d translateZ
will-change
video iframe 标签
通过动画实现的 opacity 动画转换
position: fixed

重绘(Repaint)和回流(Reflow)

重绘是当节点需要更改外观⽽不会影响布局,⽐如改变 color 就叫称为重绘

布局或者⼏何属性需要改变就称为回流

回流必定会发⽣重绘,重绘不⼀定会引发回流。回流所需的成本⽐重绘⾼的
多,改变深层次的节点很可能导致⽗节点的⼀系列回流

重绘和回流其实和 Event loop 有关

Event loop 执⾏完 Microtasks 后,会判断 document 是否需要更新。因为浏览

器是 60Hz 的刷新率,每 16ms 才会更新⼀次。 然后判断是否有 resize 或者 scroll ,有的话会去触发事件,所以 resize scroll 事件也是⾄少 16ms 才会触发⼀次,并且⾃带节流功能。

判断是否触发了 media query(媒介查询)更新动画并且发送事件

判断是否有全屏操作事件

执⾏ requestAnimationFrame 回调

执⾏ IntersectionObserver 回调,该⽅法⽤于判断元素是否可⻅,可以⽤于懒加载

上,但是兼容性不好

减少重绘和回流

使⽤ translate 替代 top

使⽤ visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流 (改变了布局)

不要使⽤ table 布局,可能很⼩的⼀个⼩改动会造成整个 table 的重新布局

动画实现的速度的选择,动画速度越快,回流次数越多,也可以选择使⽤

requestAnimationFrame

CSS 选择符从右往左匹配查找,避免 DOM 深度过深

将频繁运⾏的动画变为图层,图层能够阻⽌该节点回流影响别的元素。⽐如对于 video

标签,浏览器会⾃动将该节点变为图层


网站公告

今日签到

点亮在社区的每一天
去签到