最后
中年危机是真实存在的,即便有技术傍身,还是难免对自己的生存能力产生质疑和焦虑,这些年职业发展,一直在寻求消除焦虑的依靠。
-
技术要深入到什么程度?
-
做久了技术总要转型管理?
-
我能做什么,我想做什么?
-
一技之长,就是深耕你的专业技能,你的专业技术。(重点)
-
独立做事,当你的一技之长达到一定深度的时候,需要开始思考如何独立做事。(创业)
-
拥有事业,选择一份使命,带领团队实现它。(创业)
一技之长分五个层次
-
栈内技术 - 是指你的前端专业领域技术
-
栈外技术 - 是指栈内技术的上下游,领域外的相关专业知识
-
工程经验 - 是建设专业技术体系的“解决方案”
-
带人做事 - 是对团队协作能力的要求
-
业界发声 - 工作经验总结对外分享,与他人交流
永远不要放弃一技之长,它值得你长期
信仰持有
。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
主要内容包括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内存泄漏的场景有哪些
-
被全局变量,函数引用,组件销毁时未清除
-
被全局事件,定时器引用,组件销毁时未清除
-
被自定义事件引用,组件销毁时未清除
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三者有什么区别
-
Ajax(Asynchronous Javascript and XML),一种技术统称
-
Fetch,一个具体的原生API 浏览器原生API,用于网络请求 和XMLHttpRequest一个级别 Fetch语法更加简洁,易用,支持Promise
-
Axios,是一个第三方库 最常用的网络请求lib 内部可用XMLHttpRequest和Fetch来实现
-
lib(库)和API(原生的函数)的区别
-
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连接
-
先建立连接(确保双方都有收发消息的能力)
-
再传输内容(如发送给一个get请求)
-
网络连接是TCP协议,传输内容是HTTP协议
-
SYN SYN+ACK ACK
四次挥手-关闭连接
1.FIN ->
2.ACK <-
3.FIN <-
4.ACK ->
复制代码
HTTP跨域时为何要发送options请求
跨域请求
-
浏览器同源策略
-
同源策略一般限制Ajax网络请求,不能跨域请求server
-
不会限制
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)有什么
单线程和异步
-
JS是单线程的(无论在浏览器还是nodejs)
-
浏览器中JS执行和DOM渲染共用一个线程
-
异步 宏任务 和 微任务 宏任务,如 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异步
-
Nodejs同样使用ES语法,也是单线程,也需要异步
-
异步任务也分:宏任务+微任务
-
但是,它的宏任务和微任务,分不同类型,有不同优先级
虚拟DOM(vdom)真的很快吗
-
vdom: Virtual DOM,虚拟DOM 用JS对象模拟DOM节点数据
-
组件化 数据视图分离,数据驱动视图 只关注业务数据,而不用再关心DOM变化
-
vdom并不快,js直接操作dom才是最快的 但”数据驱动视图“要有合适的技术方案,不能全部dom重建 vdom就是目前最合适的技术方案(并不是因为它快,而是合适)
遍历一个数组用for和forEach哪个更快
-
for更快
-
forEach每次都要创建一个函数来调用,而for不会创建函数
-
函数需要独立的作用域,会有额外的开销
nodejs如何开启多进程,进程如何通讯-进程和线程的
进程 process vs 线程 thread 进程,OS 进行资源分配和调度的最小单位,有独立内存空间 线程,OS 进行运算调度的最小单位,共享进程内存空间 JS是单线程的,但可以开启多进程执行,如WebWorker js 不可以开启一个线程
为何需要多进程?
-
多核CPU,更适合处理多进程
-
内存较大,多个进程才能更好的利用(单进程有内存上限)
-
总之,“压榨”机器资源,更快,更节省 单个进程内存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的实现原理
-
JS无法直接调用 native API
-
需要通过一些特定的“格式”来调用
-
JS Bridge的常见实现方式
-
注册全局API
-
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引起的关注
-
组建树转换为链表,可分段渲染
-
渲染时可以暂停,去执行其他高优任务,空闲时再继续渲染
-
如何判断空闲? - requestIdleCallback
区别
-
requestAnimationFrame 每次渲染完都会执行,高优
-
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)