Web前端最新【面试题】2024前端面试知识体系_pxtpc,2024年最新前端大厂面试题来袭

最后

中年危机是真实存在的,即便有技术傍身,还是难免对自己的生存能力产生质疑和焦虑,这些年职业发展,一直在寻求消除焦虑的依靠。

  • 技术要深入到什么程度?

  • 做久了技术总要转型管理?

  • 我能做什么,我想做什么?

  • 一技之长,就是深耕你的专业技能,你的专业技术。(重点)

  • 独立做事,当你的一技之长达到一定深度的时候,需要开始思考如何独立做事。(创业)

  • 拥有事业,选择一份使命,带领团队实现它。(创业)

一技之长分五个层次

  • 栈内技术 - 是指你的前端专业领域技术

  • 栈外技术 - 是指栈内技术的上下游,领域外的相关专业知识

  • 工程经验 - 是建设专业技术体系的“解决方案”

  • 带人做事 - 是对团队协作能力的要求

  • 业界发声 - 工作经验总结对外分享,与他人交流

永远不要放弃一技之长,它值得你长期信仰持有

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

主要内容包括html,css,html5,css3,JavaScript,正则表达式,函数,BOM,DOM,jQuery,AJAX,vue 等等。

<style>
 #container {
  width: 200px;
  height: 200px;
  position: relative;
  background-color: #ccc;
 }
 #box {
  width: 100px;
  height: 100px;
  position: absolute;
  left: 50%;
  top: 50%;
  margin-top: -50px;
  margin-left: -50px;
  background-color: blue;
 }
</style>
<divid="container"><divid="box"></div></div>复制代码

em 和 rem


  • em 相对于当前元素的 font-size

  • rem 相对于根节点的 font-size

<div style="font-size: 20px;">
 <pstyle="text-indent: 2em; font-size: 40px;">首行缩进</p>// font-size: 40px; text-indent: 80px;<pstyle="text-indent: 2em;">哪吒, 算法猫叔</p>// font-size: 20px; text-indent: 40px;
</div>
复制代码
<style>
 @media only screen and (max-width: 374px) {
  // iphone5 或者更小的尺寸,以 iphone5 的宽度(320px)比例设置 font-size
  html {
   font-size: 86px;
  }
 }
 @media only screen and (min-width: 375px) and (max-width: 413px) {
  // iphone6/7/8 和 iphone x
  html {
   font-size: 100px;
  }
 }
 @media only screen and (min-width: 414px) {
  // iphone6p 或者更大的尺寸,以 iphone6p 的宽度(414px)比例设置 font-size
  html {
   font-size: 110px;
  }
 }
 p {
  font-size: .16rem;
 }
</style>
复制代码

vw / vh


  • vw 屏幕宽度的 1%

  • vh 屏幕高度的 1%

  • vmin 两者的最小值,vmax 两者的最大值

<div id="div1"> div1 </div>
<divid="div2"> div2 </div><divid="div3"> div3 </div><style>div {
  border: 1px solid #ccc;
  margin-top: 20px;
 }
 #div1 {
  width: 10vw;
  height: 10vh;
 }
 #div2 {
  width: 10vmax;
  height: 10vmax;
 }
 #div3 {
  width: 10vmin;
  height: 10vmin;
 }
</style>复制代码

什么时候不能使用箭头函数

箭头函数有什么缺点?


  • 没有 arguments

  • 无法通过 apply call bind 改变 this

  • 某些箭头函数代码难以阅读

什么时候不能使用箭头函数?


  • 不适用-对象方法
const obj = {
 name: '哪吒,B站,算法猫叔',
 getName: () => {
  returnthis.name
 }
}
console.log(obj.getName())
复制代码
  • 不适用-原型方法
const obj = {
 name: '哪吒,B站,算法猫叔'
}
obj.__proto__.getName = () => {
 returnthis.name
}
console.log( obj.getName() )
复制代码
  • 不适用-构造函数
constFoo = (name, age) => {
 this.name = name
 this.age = age
}
const f = newFoo('张三', 20)
// 报错 Foo is not a constructor复制代码
  • 不适用-动态上下文中的回调函数
const btn1 = document.getElementById('btn1')
btn1.addEventListener('click', () => {
 // console.log(this === window)this.innerHTMl = 'clicked'
})
复制代码
  • 不适用-Vue生命周期和method : vue组件本质上一个 JS 对象

  • React 组件(非Hooks)本质上是一个 es6 class,class里面适用箭头函数没问题

{
 data() { return { name:  '哪吒,B站:算法猫叔' } },
 methods: {
  getName: () => {
   // 报错 Cannot read properties of undefined (reading 'name')returnthis.name
  },
  // getName() {//  return this.name // 正常// }
 },
 mounted: () => {
  // 报错
 },
 // mounted() {//  正常// }
}
复制代码

JS中for-in和for-of有什么区别

for of 去遍历可以generator

const arr = [10, 20, 30]
for (let val of arr) {
 console.log(val); // 值
}

const str = 'abc'for (let c of str) {
 console.log(c);
}

functionfn() {
 for (let arg ofarguments) {
  console.log(arg)
 }
}
fn(100, 200, 'aaa')

const pList  = document.getElementsByTagName('p')
// querySelectorAll('p')for (let p of pList) {
 console.log(p)
}
复制代码
  • 遍历对象: for … in 可以,for … of 不可以

  • 遍历Map Set:for…of 可以,for…in 不可以

  • 遍历generator:for…of 可以,for … in 不可以

对象,数组,字符串可枚举的,就可以使用for ... in 循环
const obj1 = { x: 100 }
Object.getOwnPropertyDescriptors(obj1)
x:
configurable: trueenumerable: truevalue: 100writeable: true复制代码
  • 可枚举 vs 可迭代

for … in 用于可枚举数据,如对象,数组,字符串,得到key

for … of 用于可迭代数据,如数组,字符串,Map,Set,得到value

for-await-of有什么作用

for await…of 用于遍历多个Promise

functioncreatePromise(val) {
 returnnewPromise((resolve) => {
  setTimeout(() => {
   resolve(val)
  }, 1000)
 })
}

(asyncfunction () {
 const p1 = createPromise(100)
 const p2 = createPromise(200)
 const p3 = createPromise(300)
 // const res1 = await p1// console.log(res1)// const res2 = await p2// console.log(res2)// const res3 = await p3// console.log(res3)const list = [p1, p2, p3]
 // Promise.all(list).then(res => console.log(res))forawait (let res of list) {
  console.log(res)
 }
})()
复制代码

offsetHeight - scrollHeight - clientHeight区别

盒子模型: width, height, padding, border, margin, box-sizing

offsetHeight offsetWidth : border + padding + content

clientHeight clientWidth: padding + content

scrollHeight scrollWidth: padding + 实际内容尺寸

HTMLCollection和NodeList有什么区

  • DOM是一颗树,所有节点都是Node

  • Node是Element的基类

  • Element是其他HTML元素的基类,如HTMLDivElement

const p1 = document.getElementById('p1')
classNode {}

// documentclassDocumentextendsNode {}
classDocumentFragmentextendsNode {}

// 文本和注释classCharacterDataextendsNode {}
classCommentextendsCharacterData {}
classTextextendsCharacterData {}

// elemclassElementextendsNode {}
classHTMLElementextendsElement {}
classHTMLDivElementextendsHTMLElement {}
classHTMLInputElementextendsHTMLElement {}
复制代码
  • HTMLCollection 是 Element 的集合

  • NodeList 是 Node 集合

<p id="p1">
 <b>node</b> vs <em>element</em>
</p>

<script>const p1 = document.getElementById('p1')
 console.log(p1.children)
 
 console.log(p1.childNodes)
 // [b,text,em,comment]</script>复制代码

划重点:

  • 获取 Node 和 Element 的返回结果可能不一样

  • 如 elem.childNodes 和 elem.children 不一样

  • 前者包含Text和Comment节点,后者不会

类数组 变成 数组

const arr1 = Array.from(list)
const arr2 = Array.prototype.slice.call(list)
const arr3 = [...list]
复制代码

Vue中computed和watch有什么区别

  • computed 用于计算产生新的数据

  • watch 用于监听现有数据

watch: {
 name(newValue, oldValue) {
  console.log('watch name', newValue, oldValue)
 }
},
computed: {
 userInfo() {
  returnthis.name + this.city
 }
}
复制代码

computed有缓存 watch没有缓存

Vue组件通讯有几种方式

props和$emit

$parent

自定义事件

$refs

$attr

provide/inject

vuex

---

$attrs $listeners

vue3 移除 $listeners

上一级没有接收到的

props: ['x'], // $attrsemits: ['getX'], // $listenersObject.keys(this.$attrs)

<l3 v-bind="$attrs"></l3>

dom结点: inheritAttrs: false

---

this.$parentthis.$refsprovide: {
 info: 'aaa'
}

provide() {
 return {
  info: computed(() =>this.name)
 }
}

---

父子组件

上下级组件(跨多级)通讯

全局组件
复制代码

Vuex中action和mutation有什么区别

mutation: 原子操作,必须同步代码

action: 可包含多个mutation;可包含异步代码

JS严格模式有什么特点

'use strict'// 全局开启functionfn() {
 'use strict'// 某个函数开启
}
复制代码
  • 全局变量必须先声明

  • 禁止使用 with

  • 创建eval作用域

  • 禁止this指向window

  • 函数参数不能重名

JS内存垃圾回收用什么算法

垃圾回收 GC

什么是垃圾回收?

functionfn1() {
 const a = 'aa'console.log(a)
 
 const obj = { x: 100 }
 console.log(obj)
}
fn1()
复制代码
functionfn2() {
 const obj = { x: 100 }
 window.obj = obj
}
fn2()


functiongetDataFns() {
 const data = {} // 闭包return {
  get(key) {
   return data[key]
  },
  set(key, value) {
   data[key] = value
  }
 }
}
const { get, set } = getDataFns()
set('x', 100)
get('x')
复制代码
引用计数(之前)

// 对象被 a 引用let a = { x: 100 }
let a1 = a
a = 10
a1 = null// 循环引用functionfn3() {
 const obj1 = {}
 const obj2 = {}
 obj1.a = obj2
 obj2.a = obj1
}
fn3()

// ie6-7 内存泄漏的 bugvar div1 = document.getElementById('div1')
div1.a = div1
div1.someBigData = {}

标记清除(现代)
// JS 根 window复制代码

JS闭包是内存泄漏吗

闭包的数据是不可以被垃圾回收的

如何检测JS内存泄漏

检测内存变化

const arr = []
for (let i = 0; i < 10 * 10000; i++) {
 arr.push(i)
}

functionbind() {
 // 模拟一个比较大的数据const obj = {
  str: JSON.stringify(arr) // 简单的拷贝
 }
 window.addEventListener('resize', () => {
  console.log(obj)
 })
}

let n = 0functionstart() {
 setTimeout(() => {
  bind()
  n++
  
  // 执行 50 次if (n < 50) {
   start()
  } else {
   alert('done')
  }
 }, 200)
}

document.getElementById('btn1').addEventListener('click', () => {
 start()
})
复制代码

JS内存泄漏的场景有哪些

  1. 被全局变量,函数引用,组件销毁时未清除

  2. 被全局事件,定时器引用,组件销毁时未清除

  3. 被自定义事件引用,组件销毁时未清除

JS内存泄漏的场景有哪些-扩展-WeakMap和Weak

// 标记清除算法const data = {}
functionfn1() {
 const obj = { x: 100 }
 data.obj = obj
}
fn1()
复制代码
const map = newMap()
functionfn1() {
 const obj = { x: 100 }
 map.set('a', obj)
}
fn1()
复制代码
// WeakMap WeakSet 弱引用
<script>
 const wMap = newWeakMap(); // 弱引用functionfn1() {
  const obj = { x: 100 }
  wMap.set(obj, 100) // WeakMap的key,只能是引用类型
 }
 fn1()
 // WeakSet
</script>
复制代码

Ajax-Fetch-Axios三者有什么区别

  1. Ajax(Asynchronous Javascript and XML),一种技术统称

  2. Fetch,一个具体的原生API 浏览器原生API,用于网络请求 和XMLHttpRequest一个级别 Fetch语法更加简洁,易用,支持Promise

  3. Axios,是一个第三方库 最常用的网络请求lib 内部可用XMLHttpRequest和Fetch来实现

  4. lib(库)和API(原生的函数)的区别

  5. fetch 和 XMLHttpRequest 全局的API

用XMLHttpRequest实现Ajax

functionajax1(url, sucessFn) {
 const xhr = newXMLHttpRequest();
 xhr.open("GET", url, false);
 xhr.onreadystatechange = function () {
  // 这里的函数异步执行if (xhr.readyState == 4) {
   if (xhr.status == 200) {
    successFn(xhr.responseText);
   }
  }
 }
 xhr.send(null);
}

functionajax2(url) {
 returnfetch(url).then(res => res.json());
}
复制代码

请描述TPC三次握手和四次挥手

建立TCP连接


  1. 先建立连接(确保双方都有收发消息的能力)

  2. 再传输内容(如发送给一个get请求)

  3. 网络连接是TCP协议,传输内容是HTTP协议

  4. SYN SYN+ACK ACK

四次挥手-关闭连接


1.FIN ->
2.ACK <-
3.FIN <-
4.ACK ->
复制代码

HTTP跨域时为何要发送options请求

跨域请求


  1. 浏览器同源策略

  2. 同源策略一般限制Ajax网络请求,不能跨域请求server

  3. 不会限制

JSONP


// www.aaa.com网页
<script>
 window.onSuccess = function(data) {
  console.log(data)
 }
</script>
<scriptsrc="https://www.bbb.com/api/getData"></script>// https://www.bbb.com... 返回了一段字符串'onSuccess({ errno: 0, data: {} })'复制代码
// CORS 配置允许跨域(服务端)
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8011") // 或者"*"
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With")
response.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS")
response.setHeader("Access-Control-Allow-Credentials", "true") // 允许跨域接收 cookie复制代码

options请求,是跨域请求之前的预检查;浏览器自行发起的,无需我们干预,不会影响实际的功能

浏览器和nodejs事件循环(EventLoop)有什么

单线程和异步


  1. JS是单线程的(无论在浏览器还是nodejs)

  2. 浏览器中JS执行和DOM渲染共用一个线程

  3. 异步 宏任务 和 微任务 宏任务,如 setTimeout setInterval 网络请求 微任务,如 promise async / await 微任务在下一轮DOM渲染之前执行,宏任务在之后执行 微任务: MutationObserver 监听DOM树的变化,Mutation observer 是用于代替 Mutation events 作为观察DOM树结构发生变化时,做出相应处理的API MutationObserver接口提供了监视对DOM树所做更改的能力。它被设计为旧的Mutation Events功能的替代品,该功能是DOM3 Events规范的一部分。

const p = document.createElement('p')
p.innerHTML = 'new paragraph'document.body.appendChild(p)

const list = document.getElementsByTagName('p')
console.log('length---', listh.length)

console.log('start')
// 渲染之后setTimeout(() => {
 const list = document.getElementsByTagName('p')
 console.log('length on timeout---', list.length) // 2alert('阻塞 timeout')
})
// 渲染之前Promise.resolve().then(() => {
 const list = document.getElementsByTagName('p')
 console.log('length on promise.then---', list.length) // 2alert('阻塞 promise')
})
console.log('end')
复制代码
// 同步任务 -> 异步任务 -> 宏任务// 微任务要比宏任务要快// Event Loop

<script>
 console.log('start')
 setTimeout(() => {
  console.log('timeout')
 })
 Promise.resolve().then(() => {
  console.log('promise then')
 ))
 console.log('end')

 // ajax(url, fn) // 300ms// Event Loop 继续监听// 宏任务 MarcoTask Queue// () => {//   console.log('timeout')// }// fn// DOM 渲染// 微任务 MicroTask Queue// () => {//   console.log('promise then')// }
</script>
复制代码

Nodejs异步


  1. Nodejs同样使用ES语法,也是单线程,也需要异步

  2. 异步任务也分:宏任务+微任务

  3. 但是,它的宏任务和微任务,分不同类型,有不同优先级

虚拟DOM(vdom)真的很快吗


  1. vdom: Virtual DOM,虚拟DOM 用JS对象模拟DOM节点数据

  2. 组件化 数据视图分离,数据驱动视图 只关注业务数据,而不用再关心DOM变化

  3. vdom并不快,js直接操作dom才是最快的 但”数据驱动视图“要有合适的技术方案,不能全部dom重建 vdom就是目前最合适的技术方案(并不是因为它快,而是合适)

遍历一个数组用for和forEach哪个更快


  • for更快

  • forEach每次都要创建一个函数来调用,而for不会创建函数

  • 函数需要独立的作用域,会有额外的开销

nodejs如何开启多进程,进程如何通讯-进程和线程的


进程 process vs 线程 thread 进程,OS 进行资源分配和调度的最小单位,有独立内存空间 线程,OS 进行运算调度的最小单位,共享进程内存空间 JS是单线程的,但可以开启多进程执行,如WebWorker js 不可以开启一个线程

为何需要多进程?

  1. 多核CPU,更适合处理多进程

  2. 内存较大,多个进程才能更好的利用(单进程有内存上限)

  3. 总之,“压榨”机器资源,更快,更节省 单个进程内存2G左右

nodejs如何开启多进程

// console.info(process.pid)const http = require('http')

const server = http.createServer()
server.listen(3000, () => {
 console.log('localhost: 3000')
})

console.info(process.pid)

// WebWorker 进程// forkconst http = require('http')
const server = http.createServer((req, res) => {
 if (req.url === '/get-sum') {
   console.info('主进程 id', process.id)
   
   res.end('hello')
 }
})
server.listen(3000, () => {
 console.info('localhost: 3000')
})

// cluster 进程复制代码
// 子进程,计算functiongetSum() {
 let sum = 0for (let i = 0; i < 10000; i++) {
  sum += i
 }
 return sum
}

process.on('message', data => {
 console.log('子进程 id', process.pid)
 console.log(‘子进程接受到的信息:', data)

 const sum = getSum()
 // 发送消息给主进程
 process.send(sum)
})
复制代码
const http = require('http')
const fork = require('child_process').forkconst server = http.createServer((req, res) => {
 if (req.url === '/get-sum') {
  console.info('主进程 id', process.pid)

   // 开启子进程const  computeProcess = fork('./compute.js')
  computeProcess.send('开始计算')

  computeProcess.on('message', data => {
    console.info('主进程接受到的信息:', data)
    res.end('sum is' + data)
  })

  computeProcess.on('close', () => {
    console.info('子进程因报错而退出')
    computeProcess.kill()
    res.end('error')
  })
 }
})

server.listen(3000, () => {
 console.info('localhost: 3000')
})
复制代码
const http = require('http')
const cpuCoreLength = require('os').cpus().lengthconst cluster = require('cluster')

if (cluster.isMaster) {
 for (let i = 0; i < cpuCoreLength; i++) {
  cluster.fork() // 开启子进程
 }
 cluster.on('exit', worker => {
  console.log('子进程退出')
  cluster.fork() // 进程守护
 })
} else {
 // 多个子进程会共享一个 TCP 连接,提供一份网络服务const server = http.createServer((req, res) => {
  res.writeHead(200)
  res.end('done')
 })
 server.listen(3000)
}
复制代码

开启子进程 child_process.fork 和 cluster.fork 使用 send 和 on 传递消息

请描述js-bridge的实现原理

  1. JS无法直接调用 native API

  2. 需要通过一些特定的“格式”来调用

  3. JS Bridge的常见实现方式

  4. 注册全局API

  5. URL Scheme

// 封装 JS-bridgeconst sdk = {
 invoke(url, data = {}, onSuccess, onError) {
   const iframe = document.createElement('iframe')
   iframe.style.visibility = 'hidden'document.body.appendChild(iframe)
   
   iframe.onload = () => {
    const content = iframe1.contentWindow.document.body.innerHTML
   }
 }
}
复制代码

requestIdleCallback和request

由React fiber引起的关注

  1. 组建树转换为链表,可分段渲染

  2. 渲染时可以暂停,去执行其他高优任务,空闲时再继续渲染

  3. 如何判断空闲? - requestIdleCallback

区别

  1. requestAnimationFrame 每次渲染完都会执行,高优

  2. requestIdleCallback 空闲时才执行,低优

<p>requestAnimationFrame</p>
<buttonid="btn1">change</button><divid="box"></div><script>const box = document.getElementById('box')
document.getElementById('btn1').addEventListener('click', () => {
 let curWidth = 100const maxWidth = 400functionaddWidth() {
  curWidth = curWidth + 3
  box.style.width = `${curWidth}px`if (curWidth < maxWidth) {
   window.requestIdleCallback(addWidth) // 时间不用自己控制
  }
 }
})
</script>复制代码
start
end
timeout
requestAnimationFrame
requestIdleCallback

window.onload = () => {

 console.info('start')
 setTimeout(() => {
  console.info('timeout')
 })
 // 宏任务,顺序交换也一样// 高优window.requestAnimationFrame(() => {


### HTTP

* HTTP 报文结构是怎样的?

* HTTP有哪些请求方法?

* GET 和 POST 有什么区别?

* 如何理解 URI?

* 如何理解 HTTP 状态码?

* 简要概括一下 HTTP 的特点?HTTP 有哪些缺点?

* 对 Accept 系列字段了解多少?

* 对于定长和不定长的数据,HTTP 是怎么传输的?

* HTTP 如何处理大文件的传输?

* HTTP 中如何处理表单数据的提交?

* HTTP1.1 如何解决 HTTP 的队头阻塞问题?

* 对 Cookie 了解多少?

* 如何理解 HTTP 代理?

* 如何理解 HTTP 缓存及缓存代理?

* 为什么产生代理缓存?

* 源服务器的缓存控制

* 客户端的缓存控制

* 什么是跨域?浏览器如何拦截响应?如何解决?  

  **[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/topics/618166371)**

![](https://img-blog.csdnimg.cn/img_convert/3a28cc7b978db5d78ce5f1c5ec78122b.png)


  • 15
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值