前端面试复习题(终)

春招上岸腾讯了,把三月份记的一些笔记按时间顺序放上来。
(只记录了网上摘录的部分,很多笔记在草稿本上,不好放上来)
同时感谢飞书前端年后面试真题,会80%直接进大厂
当然欢迎感兴趣学习方式的同学私信我。

文章目录

    • 1.闭包
    • 2.如何改变this指针
    • 3.深浅拷贝
    • 4.position的值
    • 5.引用CSS的方法
    • 6.为什么js放在html最末端
    • 7.设计模式
    • 8.常见状态码
    • 9.Ajax readystate状态
    • 10.浏览器缓存机制
    • 11.类数组转换成数组的方法
    • 12.js异步
    • 13.async和await
    • 14.HTTP1.0、HTTP1.1、HTTP2.0、HTTP3.0的主要区别
    • 15.文档流和文本流
    • 16.事件流
    • 17.函数声明方式
    • 18.事件循环
    • 19.原型链补充
    • 20.正则表达式
    • 21.遍历数组的方法
    • 22.类型检测的方法
    • 23.arguments.callee即递归
    • 24.进程与线程
    • 25.进程通信IPC(InterProcess Communication)
    • 26.进程调度策略
    • 27.死锁
    • 28.I/O多路复用
    • 29.性能优化
    • 30.vue双向绑定
    • 31.虚拟DOM
    • 32.跨域
    • 33.页面加载慢的原因
    • 34.防抖和节流
    • 35.BFC
    • 36.js 继承的多种方式
    • 37.v8垃圾回收策略
    • 38.性能优化

1.闭包

「每日一题」JS 中的闭包是什么?
详解js中的闭包
js闭包的应用

闭包是指那些能够访问自由变量的函数。自由变量是指在函数中使用的既不是函数参数也不是函数的局部变量的变量。

闭包的作用:

当有个函数的内部有个局部变量(n),这个变量无法在外面直接得到时,我们通过在这个函数里面在定义一个函数,并且用这个定义的函数去得到这个局部变量,最后我们在返回这个子函数,就能通过返回的这个函数得到局部变量n

闭包的优点:

  • 保护函数内的变量安全。
  • 在内存中维持一个变量。
  • 读取函数内部的变量,因为链式作用域的结构,子对象会一级一级向上寻找所有父对象的变量,即父对象的所有变量对子对象都是可见的,反之则不成立。
  • 方便调用上下文的局部变量。
  • 加强封装性,达到对变量的保护。

闭包的缺点:

  • 常驻内存,会增大内存的使用量,使用不当容易造成内存泄漏。
  • 内存浪费,会产生无用内存。

2.如何改变this指针

通过bind, call, apply三种方式改变某函数的this指向。

三者的区别:

①call和apply两者与bind的区别为:前两者返回的是执行结果,而后者返回的是改变了this指向的函数,如需执行结果则需再调用一次。
②call和apply的区别为:前者传递的是多个参数,后者传递的是一个包含多个参数的类数组。

3.深浅拷贝

如何写出一个惊艳面试官的深拷贝
乞丐版:JSON.parse(JSON.stringify());

JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串。
JSON.parse()可以把JSON规则的字符串转换为JSONObject

常规版

function clone(target, map = new Map()) {
    if (typeof target === 'object') {
        let cloneTarget = Array.isArray(target) ? [] : {};
        if (map.get(target)) {
            return target;
        }
        map.set(target, cloneTarget);
        for (const key in target) {
            cloneTarget[key] = clone(target[key], map);
        }
        return cloneTarget;
    }else{
        return target;
    }
}

4.position的值

  • absolute:生成绝对定位的元素,相对于static定位以外的第一个父元素进行定位。
  • fixed:生成绝对定位的元素,相对于浏览器窗口进行定位。
  • relative:生成相对定位的元素,相对于正常位置进行定位。
  • static:默认值。没有定位,元素出现在正常的流中。
  • inherit:规定应该从父元素继承position属性的值。

5.引用CSS的方法

怎么调用CSS样式

  • ①行内式

文字颜色为红色

  • ②嵌入式
使用style标签把css代码放在特定页面的部分中

  • ③外链式

其中,rel规定当前文档与被链接文档的关系;href规定被链接文档的位置;type规定被链接文档的MIME类型。stylesheet表引入的是外部样式表,text/css表示MIME中的css类型。

6.为什么js放在html最末端

为什么要把js放在页面底部,css放在顶部
JS 一定要放在 Body 的最底部吗

因为浏览器生成Dom树的时候是一行一行读HTML代码的,script标签放在最后面就不会影响前面的页面的渲染。
因为此时dom树已经解析完成, 不然会阻塞dom的解析。

7.设计模式

前端技术之MVVM软件架构模式

常用的设计模式:创建型模式、结构型模式、行为模式。

重构:设计模式是理想主义(为理想的软件设计提供目标,但是达到这个目标通常很困难,很可能存在过度设计)、重构是实用主义(满足当前需求设计同时,在版本迭代中不断改进当前的设计,尽量靠近设计模式的理想过度,相辅相成的关系,设计模式为重构提供目标,在不断重构中达到理想状态)

8.常见状态码

200、204、206(可以展开HTTP1.1)
301、302、303、304(可以展开浏览器缓存机制)
400、401、403、404
500、502、503

9.Ajax readystate状态

数字 状态 说明
0 unsent 代理被创建未调用open()
1 opend 已open(),建立连接
2 headers_received 已send(),获取状态行和响应头
3 loading 响应体下载中
4 done 响应体下载完成,可直接使用responseText

10.浏览器缓存机制

彻底理解浏览器的缓存机制(http缓存机制)

强缓存:expires、cache-control.
协商缓存Etag和If-None-Match、Last-Modefied和If-Modified-Since.

11.类数组转换成数组的方法

类数组转换成数组的方法

  • ①Array.prototype.slice.call()
  • ②Array.from()
  • ③扩展运算符… var args = […arguments];

12.js异步

js异步从入门到放弃(一)- Event Loop模型
js异步从入门到放弃(二)- 传统的异步实现方案
js异步从入门到放弃(三)- 异步任务队列(task queues)
js异步从入门到放弃(四)- Generator 封装异步任务
js异步从入门到放弃(实践篇) — 常见写法&面试题解析

13.async和await

理解 JavaScript 的 async/await
async和await

await 是个运算符,用于组成表达式,await 表达式的运算结果取决于它等的东西。

  • ①如果它等到的不是一个 Promise 对象,那 await 表达式的运算结果就是它等到的东西。
  • ②如果它等到的是一个 Promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 Promise 对象fulfilled,然后得到 resolve 的值,作为 await 表达式的运算结果。

async 函数调用不会造成阻塞,它内部所有的阻塞都被封装在一个 Promise 对象中异步执行。

14.HTTP1.0、HTTP1.1、HTTP2.0、HTTP3.0的主要区别

HTTP1.0和HTTP1.1和HTTP2.0的区别
HTTP1.0、HTTP2.0、HTTP 3.0及HTTPS简要介绍

15.文档流和文本流

HTML 的文档流和文本流分别是什么?

文档流是相对于盒子模型讲的,文本流是相对于文子段落讲的。

元素浮动(float)之后,会让它跳出文档流,也就是说当它后面还有元素时,其他元素会无视它所占据了的区域,直接在它身下布局。但是文字却会认同浮动元素所占据的区域,围绕它布局,也就是没有拖出文本流。
元素绝对定位(absolute)后,不仅元素盒子会拖出文档流,文字也会出文本流。那么后面元素的文本就不会在认同它的区域位置,会直接在它后面布局,不会再环绕。

回归标准文档流:

flaot的元素,对父级元素设置overflow: hidden或clear: both,或者对float的元素同时使用clear: both可以回归文档流。

16.事件流

博客园
彻底理解js的事件流

用户的操作会产生事件,事件会在dom元素上进行传播,传播方向:div>body>html>document>window.
事件分为三个阶段:捕获阶段>目标阶段(当前dom上执行的js)>冒泡阶段(向父级dom传播),一般会在冒泡阶段进行干预,例如在页面和页面弹框中都捕获了enter回车事件,一般会在弹框层阻止向上冒泡event.stopPropogation();

事件监听器element.addEventListener(event, function, useCapture);
第一个参数是事件的类型(如“ click”或“ mousedown”)。
第二个参数是我们想要在事件发生时调用的函数。
第三个参数是一个布尔值,指定是使用事件冒泡还是事件捕获。true为捕获,flase为冒泡,默认为flase。
所有事件的顺序是:其他元素捕获阶段事件 -> 本元素代码顺序事件 -> 其他元素冒泡阶段事件。

17.函数声明方式

①function myFuction(a,b){
	return a*b;
}
②var x = function (a,b){
	return a*b;
}
③var myFunction = new Function("a","b","return a*b");
var x = myFuction(4,3);

18.事件循环

详解JavaScript中的Event Loop(事件循环)机制
以下事件属于宏任务:

setInterval()
setTimeout()

以下事件属于微任务:

new Promise()
new MutaionObserver()

当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行。

19.原型链补充

JS CLass类
用实例的_proto_属性为class添加方法

var p1 = new Point(2,3);
var p2 = new Point(3,2);

p1.__proto__.printName = function () { return 'Oops' };

p1.printName() // "Oops"
p2.printName() // "Oops"

var p3 = new Point(4,2);
p3.printName() // "Oops"

20.正则表达式

JS正则表达式入门,看这篇就够了

正则表达式即浏览器可以识别的规则,有了这个规则,浏览器就可以帮我们判断某些字符是否符合我们的要求。

定义:

//第一种“/正则表达式/”
    var reg1=/hello \w{3,12}/g;
//第二种new RegExp('正则表达式')
    var reg2=new RegExp("hello \\w{3,12}",'g');

修饰符:

g:全局匹配;i:不区分大小写;m:多行匹配

属性:

global、ignoreCase、lastIndex、multiline、source

方法:

test()、exec()、compile()

例子:检验九位qq号(用^和$指定起止位置)

/^[1-9][0-9]{4,14}$/

String对象里的方法:match()、search()、replace()、split();

21.遍历数组的方法

面试官连环追问:数组拍平(扁平化) flat 方法实现

const arr = [1, 2, 3, 4, [1, 2, 3, [1, 2, 3, [1, 2, 3]]], 5, "string", { name: "弹铁蛋同学" }];
// 遍历数组的方法有太多,本文只枚举常用的几种
// for 循环
for (let i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}
// for...of
for (let value of arr) {
  console.log(value);
}
// for...in
for (let i in arr) {
  console.log(arr[i]);
}
// forEach 循环
arr.forEach(value => {
  console.log(value);
});
// entries()
for (let [index, value] of arr.entries()) {
  console.log(value);
}
// keys()
for (let index of arr.keys()) {
  console.log(arr[index]);
}
// values()
for (let value of arr.values()) {
  console.log(value);
}
// reduce()
arr.reduce((pre, cur) => {
  console.log(cur);
}, []);
// map()
arr.map(value => console.log(value));

22.类型检测的方法

const arr = [1,2,3];
①arr instanceof Array
②arr.constructor === Array
③Object.prototype.toString.call(arr) === '[object Array]'
④Array.isArray(arr)

23.arguments.callee即递归

24.进程与线程

一篇让你明白进程与线程之间的区别与联系

进程是系统资源分配的最小单位,线程是cpu调度的最小单位。
进程间通过TCP/IP端口来交互,线程通过共享内存交互。
一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。

25.进程通信IPC(InterProcess Communication)

进程间通信IPC
六种通信方式:
Ⅰ、本地进程通信

  • ①管道/匿名管道(pipe)
  • ②有名管道
  • ③信号量
  • ④消息队列
  • ⑤共享内存

Ⅱ、网络间进程通信

  • ⑥socket套接字
    套接字三个属性:域、端口号、协议类型

26.进程调度策略

  • ①先来先服务算法(FCFS)
  • ②短作业优先调度算法(SJF)
  • ③高响应比优先算法(HRRN)
  • ④时间片轮转算法
  • ⑤多级反馈队列算法

27.死锁

造成死锁必须达到的4个条件:

  • ①互斥:一个资源每次只能被一个线程使用。
  • ②请求与保持:一个线程因请求资源而阻塞时,对已获得的资源保持不放。
  • ③不可剥夺:线程已获得的资源再未使用完前不可强行剥夺。
  • ④循环等待:若干线程之间形成头尾相接的循环等待资源关系。

银行家算法(避免死锁):

在资源分配之前先计算此次分配资源的安全性,若分配后不会造成系统进入不安全状态则分配否则等待。

28.I/O多路复用

I/O 多路复用引入了一些额外的操作和开销,性能更差。但是好处是用户可以在一个线程内同时处理多个 I/O 请求。如果不采用 I/O 多路复用,则必须通过多线程的方式,每个线程处理一个 I/O 请求。

29.性能优化

Ⅰ、评判标准:

RAIL:100ms内响应用户的输入,10ms内产生一帧,最大化主线程空闲时间,5s内让页面变得可交互。
R:复杂的js计算尽可能放在后台,避免对用户输入造成阻塞。
A:在一些高压点上,比如动画,尽可能地少做事(如取offst/设置style等操作)
I:用空闲时间来完成一些延后的工作,如先加载页面可见部分,然后利用空闲时间加载剩余部分。
L:禁用渲染阻塞的资源,延后加载

Ⅱ、重排重绘:

减少重排次数和范围:
①样式集中改变
②分离读写操作(不要在两个读操作间加写操作)
③将DOM离线(给元素设置display:none将其从dom渲染树上拿掉,复制节点到dom上)
④使用absolute或fixed脱离文档流。

Ⅲ、将css放将js放底部,避免阻塞dom树的渲染。

Ⅳ、网页图片加载优化:

①优先加载首屏所需图片
②在 HTTP/1.0 和 HTTP/1.1 协议下,由于 Chrome 只支持同域同时发送 6 个并发请求,可以进行域名切分,来提升并发的请求数量,或者使用 HTTP/2 协议
③单位像素优化(减少色板中颜色种类)
④图片像素总数优化(将图片加载尺寸和实际渲染尺寸对比,减少图片大小)

Ⅴ、白屏(从打开一个页面到页面展示画面经历的过程):

  1. DNS域名解析,获取到服务器的IP地址
    ①DNS缓存优化
    ②DNS预加载策略
    ③稳定可靠的DNS服务器
  2. 建立TCP请求连接
  3. 服务端对请求处理响应
    服务端的处理优化,是一个非常庞大的话题,会涉及到如Redis缓存、数据库存储优化或是系统内的各种中间件以及Gzip压缩等
  4. 客户端下载、解析、渲染显示页面
    ①尽可能精简HTML的代码和结构
    ②尽可能优化
    ③一定要合理放置JS代码,尽量不要使用内联的JS代码

Ⅵ、动画性能优化:

①使用精简的DOM
②提倡使用div+css,避免使用table布局因为后者重排和重绘成本较高
③DOM元素读写分离
④让进行大量动画的元素脱离文档流,减少重排开销
⑤缓存DOM元素位置信息,避免不必要的属性读取
⑥尽量使用离线DOM
⑦使用css3 transform优化动画性能
⑧合成层:一般一个元素开启硬件加速后会变成合成层,可以独立于普通文档流中,改动后可以避免整个页面重绘,提升性能。

30.vue双向绑定

30 道 Vue 面试题,内含详细讲解
View变化更新Data:事件监听。
Data变化更新View:

  • ①实现一个监听器Observer:对数据对象遍历,包括子对象的属性,用Object.defineProperty()对属性加上setter和getter(注:Vue3.0中使用proxy)
  • ②实现一个解析器Compile
  • ③实现一个订阅者Watcher
  • ④实现一个订阅器Dep

31.虚拟DOM

优点:

①保证性能下限、②无需手动操作DOM③跨平台

缺点:

无法进行极致优化:在一些性能要求极高的应用中无法进行针对性的极致优化。

实现原理:

①用JS对象模拟真实的DOM树,对真实的DOM进行抽象
②用diff算法比较两颗DOM树的差异
③用patch算法将两个DOM对象的差异应用到真正的DOM树上

32.跨域

跨域资源共享 CORS 详解
什么是跨域?跨域解决方法
解决跨域的方法:

  • ①设置document.domain解决无法读取非同源网页的cookie问题
  • ②跨文档通信API:window.postMessage()
  • ③JSONP(就是动态创建script标签,然后利用script的src 不受同源策略约束来跨域获取数据)
  • ④CORS
  • ⑤Nginx

CORS需要浏览器和服务器同时支持。
浏览器端自动完成,不需要用户参与,所以CORS通信的关键是服务器。
①对于简单请求,浏览器会直接发出CORS请求,即在头信息中添加一个Origin字段(包含协议+域名+端口)。
②对于非简单请求,浏览器会先发出一次预检请求。

33.页面加载慢的原因

  • ①后端的原因,服务器不太好,请求耗时长
  • ②前端发送请求太多
  • ③网络卡顿,存在丢包
  • ④图片过大

34.防抖和节流

浅谈 JS 防抖和节流

35.BFC

博客园
BFC——块格式化上下文
应用:

  • ①margin重叠
  • ②浮动元素高度塌陷,清除浮动
  • ③BFC 可以阻止元素被浮动元素覆盖
  • ④自适应两列布局,左边宽度固定,右边自适应(不过自适应布局建议用flex)

36.js 继承的多种方式

原型链继承、构造函数继承、组合继承、原型链继承、寄生式继承、寄生组合式继承

37.v8垃圾回收策略

聊聊V8引擎的垃圾回收

38.性能优化

Ⅰ、减少请求数量

  • ①合并文件
  • ②图片处理,雪碧图,Base64
  • ③减少临时重定向
  • ④使用缓存
  • ⑤减少使用CSS的@import

Ⅱ、减小资源大小

  • ①HTML压缩
  • ②CSS压缩
  • ③JS压缩
  • ④图片压缩(webp)
  • ⑤开启gzip

Ⅲ、优化网络连接

  • ①使用CDN
  • ②使用DNS预解析
  • ③并行连接
  • ④并行连接
  • ⑤keepalive持久连接
  • ⑥管道化连接,多路复用

Ⅳ、优化资源加载

  • ①资源加载位置
    -css放在head中,先外链,后本页
    js放在body底部,先外链,后本页
    body中间尽量不写css或者script
  • ②资源加载时机
    异步script标签
    defer:异步加载,HTML解析完成后执行
    async:异步加载,加载完成后立即执行
    模块按需加载
    webpack的require.ensure
    资源预加载
    资源懒加载

Ⅴ、减少重绘、回流

  • ①样式设置,图片预先占位
  • ②渲染层,某些元素可以用absolute
  • ③DOM优化,事件代理、防抖节流

Ⅵ、webpack优化

  • ①打包公共代码
  • ②动态导入和按需加载
  • ③剔除无用代码
  • ④长缓存优化

你可能感兴趣的:(前端自学笔记,前端,面试,大厂,春招,复习)