最后
你要问前端开发难不难,我就得说计算机领域里常说的一句话,这句话就是『难的不会,会的不难』,对于不熟悉某领域技术的人来说,因为不了解所以产生神秘感,神秘感就会让人感觉很难,也就是『难的不会』;当学会这项技术之后,知道什么什么技术能做到什么做不到,只是做起来花多少时间的问题而已,没啥难的,所以就是『会的不难』。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
我特地针对初学者整理一套前端学习资料
console.log©;
}
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§
}
复制代码
* 遍历对象: 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 集合
node vs element
复制代码
划重点:
* 获取 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’], // l i s t e n e r s O b j e c t . k e y s ( t h i s . listenersObject.keys(this. listenersObject.keys(this.attrs)
dom结点: inheritAttrs: false
this.
p
a
r
e
n
t
t
h
i
s
.
parentthis.
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 弱引用
复制代码
## 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. 不会限制<link> <img> <script> <iframe>加载第三方资源
### JSONP
---
// www.aaa.com网页
<scriptsrc=“https://www.bbb.com/api/getData”>// 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§
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
复制代码
### 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的常见实现方式
1. 注册全局API
2. 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
区别
4. requestAnimationFrame 每次渲染完都会执行,高优
5. requestIdleCallback 空闲时才执行,低优
requestAnimationFrame
start
end
timeout
requestAnimationFrame
requestIdleCallback
window.onload = () => {
console.info('start')
setTimeout(() => {
console.info('timeout')
})
// 宏任务,顺序交换也一样// 高优window.requestAnimationFrame(() => {
console.info('requestAnimationFrame')
})
// 低优window.requestIdleCallback(() => {
console.info('requestIdleCallback')
})
console.info('end')
}
复制代码
Vue每个生命周期都做了什么
-
beforeCreate 创建一个空白的Vue实例 data method 尚未被初始化,不可使用
-
created vue实例初始化完成,完成响应式绑定 data method都已经初始化完成,可调用 尚未开始渲染模板
-
beforeMount 编译模版,调用render生成vdom 还没有开始渲染DOM
$el null element没有
-
mounted 完成DOM渲染 组件创建完成 开始由“创建阶段”进入“运行阶段”
-
beforeUpdate data发生变化之后 准备更新DOM(尚未更新DOM)
-
updated data发生变化,且DOM更新完成 (不要在updated中修改data,可能会导致死循环)
-
beforeUnmount 组件进入销毁阶段(尚未销毁,可正常使用) 可移除,解绑一些全局事件,自定义事件
-
unmounted 组件被销毁了 所有子组件也都被销毁了
-
keep-alive组件 onActivated 缓存组件被激活 onDeactivated 缓存组件被隐藏
<keep-alive>
<Child1v-if="num === 1"></Child1><Child2v-else></Child2>
</keep-alive>
// Child1 2created() {
console.log() // keep-alive 中只创建
}
activated() {}
deactivated() {}
// 创建一次被缓存复制代码
child1 created
child1 activated
child2 created
child1 deactivated
child2 activated
child2 deactivated
child1 activated
复制代码
- vue什么时候操作DOM比较合适 mounted和updated都不能保证子组件全部挂载完成 使用$nextTick渲染DOM
只有nextTick操作DOM才是最安全的
$nextTick
mounted() {
this.$nextTick(function () {
// 仅在整个视图都被渲染之后才会运行的代码
})
}
复制代码
-
ajax 应该在那个生命周期? 有两个选择:created 和 mounted 推荐:mounted
-
vue3 Composition API 生命周期有何区别? 用setup代替了beforeCreate和created 使用Hooks函数的形式,如mounted改为onMounted()
import { onUpdated, onMounted } from'vue'exportdefault {
setup() {
onMounted(() => {
})
onUpdated(() => {
})
}
}
复制代码
Vue2和Vue3和React三者的diff算法有什么
介绍diff算法 diff算法很早就有
tree diff优化 只比较同一层级,不跨级比较 tag 不同则删掉重建(不再去比较内部的细节) 子节点通过key区分(key的重要性)
vue3最长递增子序列 vue2 双端比较 React 仅右移
Vue-router的MemoryHistory是什么
Hash, WebHistory, MemoryHistory( v4 之前叫做 abstract history)
移动端H5点击有300ms延迟,该如何解决
FastClick原理 监听touchend事件(touchstart touchend会先于click触发) 使用自定义DOM事件模拟一个click事件 把默认的click事件(300ms之后触发)禁止掉
现代浏览器的改进
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
</head>
复制代码
HTTP请求中token和cookie有什么区别-cookie
-
cookie HTTP无状态,每次请求都要带cookie,以帮助识别身份 服务端也可以向客户端set-cookie,cookie大小限制4kb 默认有跨域限制:不可跨域共享、传递cookie
-
withCredentials 前端设置跨域cookie共享 cookie本地存储 HTML5之前cookie常被用于本地存储 HTML5之后推荐使用localStorage和sessionStorage
-
现在浏览器开始禁止第三方cookie 和跨域限制不同。这里是:禁止网页引入的第三方JS设置cookie 打击第三方广告,保护用户隐私 新增属性 SameSite: Strict/Lax/None;值可自己选择
-
浏览器的Cookie新增加了一个SameSite属性,用来防止CSRF攻击和用户追踪
-
cookie和session cookie用于登录验证,存储用户标识 session在服务端,存储用户详细信息,和cookie信息一一对应 cookie和session是常见登录验证解决方案
HTTP请求中token和cookie有什么区别-token
-
token vs cookie cookie是HTTP规范,而token是自定义传递 cookie会默认被浏览器存储,而token需自己存储 token默认没有跨域限制
-
jwt (json web token) 可以取代 cookie和session 前端发起登录,后端验证成功之后,返回一个加密的token 前端自行存储这个token(其中包含了用户信息,加密了) 以后访问服务端接口,都带着这个token,作为用户信息
-
cookie:HTTP标准;跨域限制;配合session使用
-
token:无标准;无跨域限制;用于JWT
session和JWT哪个更好
-
session缺点 占用服务端内存,硬件成本高 多进程,多服务器时,不好同步,需使用第三方缓存,如redis 默认有跨域限制
-
session优点 原理简单,易于学习 用户信息存储在服务端,可快速禁某个用户
-
jwt 优点 不占用服务端内存 多进程,多服务器 不受影响 没有跨域限制
-
jwt 缺点 用户信息存储在客户端,无法快速封禁某用户 万一服务端秘钥被泄漏,则用户信息全部丢失 token体积一般大于cookie,会增加请求的数据量
如有严格管理用户信息的需求(保密,快速封禁)推荐session 如没有特殊要求,则使用jwt
如何实现SSO单点登录
-
基于cookie cookie默认不可跨域共享,但有些情况下可设置为共享 主域名相同,如www.baidu.com image.baidu.com 设置cookie domain为主域名,即可共享cookie
-
sso 主域名完全不同,则cookie无法共享 可使用sso技术方案
HTTP协议和UDP协议有什么区别
网络协议 HTT P协议在应用层 TCP UDP 协议再传输层 严格来说,应该拿TCP和UDP进行比较
OSI的体系结构
7. 应用层
6. 表示层
5. 会话层
4. 运输层
3. 网络层
2. 数据链路层
1. 物理层
复制代码
TCP/IP的体系结构
1. 应用层(各种应用层协议,如DNS,HTTP,SMTP等)
### 最后
![](https://img-blog.csdnimg.cn/img_convert/99c58ff6374dd01890c551a7805e10e0.webp?x-oss-process=image/format,png)
![](https://img-blog.csdnimg.cn/img_convert/90059f81c5b34d4e558d1a086e979214.webp?x-oss-process=image/format,png)
**资料过多,篇幅有限**
**[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)**
>自古成功在尝试。不尝试永远都不会成功。勇敢的尝试是成功的一半。
4. token:无标准;无跨域限制;用于JWT
## session和JWT哪个更好
1. session缺点 占用服务端内存,硬件成本高 多进程,多服务器时,不好同步,需使用第三方缓存,如redis 默认有跨域限制
2. session优点 原理简单,易于学习 用户信息存储在服务端,可快速禁某个用户
3. jwt 优点 不占用服务端内存 多进程,多服务器 不受影响 没有跨域限制
4. jwt 缺点 用户信息存储在客户端,无法快速封禁某用户 万一服务端秘钥被泄漏,则用户信息全部丢失 token体积一般大于cookie,会增加请求的数据量
如有严格管理用户信息的需求(保密,快速封禁)推荐session 如没有特殊要求,则使用jwt
## 如何实现SSO单点登录
1. 基于cookie cookie默认不可跨域共享,但有些情况下可设置为共享 主域名相同,如[www.baidu.com](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0) [image.baidu.com](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0) 设置cookie domain为主域名,即可共享cookie
2. sso 主域名完全不同,则cookie无法共享 可使用sso技术方案
## HTTP协议和UDP协议有什么区别
网络协议 HTT P协议在应用层 TCP UDP 协议再传输层 严格来说,应该拿TCP和UDP进行比较
OSI的体系结构
- 应用层
- 表示层
- 会话层
- 运输层
- 网络层
- 数据链路层
- 物理层
复制代码
TCP/IP的体系结构
- 应用层(各种应用层协议,如DNS,HTTP,SMTP等)
最后
[外链图片转存中…(img-EXDVKIso-1715447978664)]
[外链图片转存中…(img-s3lXCkOR-1715447978664)]
资料过多,篇幅有限
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
自古成功在尝试。不尝试永远都不会成功。勇敢的尝试是成功的一半。