面试题
1、下面代码输出啥?
function Person(firstName,lastName){
this.firstName = firstName;
this.lastName = lastName;
}
const lydia = new Person("Ly","2")
const sa = Person("s","l")
console.log(lydia)
console.log(sa)2、以下代码各有什么效果?
<script src="..." defer></script>
<script src="..." async></script>
<link rel="prefetch" href="..."/>
<link rel="preload" href="..."/>defer : 不阻塞DOM 解析,DOM解析完成后按顺序执行
async: 不阻塞DOM 解析,下载完成后立即执行
prefetch: 立即加载
preload: 空闲时加载 ,优先级比较低,有些资源不是立马就用到
3、创建一个webworker时如何不指定特定的文件?
1.常规写法
// 常规写法
new WebWorker("./worker.js")2.ObjectUrl 方法
// 定义 Worker 逻辑函数
const workerFunction = () => {
onmessage = (e) => {
const result = e.data * 2;
postMessage(result);
};
};
// 将函数转为字符串并包装为 Blob
const blob = new Blob([`(${workerFunction.toString()})()`], { type: 'text/javascript' });
// 生成 Object URL 并创建 Worker
const worker = new Worker(URL.createObjectURL(blob));
// 使用示例
worker.postMessage(10);
worker.onmessage = (e) => {
console.log('Received:', e.data); // 输出 20
};3.Data URL方法
const workerCode = `
onmessage = function(e) {
postMessage(e.data.toUpperCase());
};
`;
// 将代码转为 Data URL
const dataURL = `data:application/javascript,${encodeURIComponent(workerCode)}`;
// 创建 Worker
const worker = new Worker(dataURL);
// 使用示例
worker.postMessage('hello');
worker.onmessage = (e) => {
console.log(e.data); // 输出 "HELLO"
};4、如何清理源码里面没有被应用的代码,主要是js,Ts,CSS代码 (工程化)
ESlint , Terser :1.文件-->AST-->分析-->...
- Tree Shaking
- css Purgecss
5、下面哪些是属于 cookie的属性
A httponly B secure C samesite D path
6、下面哪种动画实现方式效率最高
A 在CSS 动画中改变元素的left (会改变布局树,重排)
B 在JS 中不断改变元素的left (会从解析开始)
C 在CSS动画中改变元素的transform (最高)
D 在JS中不断改变元素的transform (解析)
C
浏览器渲染原理
主线程:dom解析->样式计算-> 布局 -> 分层 -> 绘制
合成线程:分块->光栅化->画
7、什么是Reflect?它有什么作用?
Reflect 对对象的基本操作
//例如获取对象的所有属性
const obj = {
a:1,
b:2,
get c(){
console.log(this)
console.log(this.a+this.b)
}
}
//比如 我要读取 obj.c
console.log(obj.c) // 触发的是Get操作有三个参数 (对象是谁,读的什么属性,this是谁) 这里没有是浏览器自动帮你把obj 丢进去了
//如果我想直接使用get操作 我可以这么做
console.log(Reflect.get(obj,'c',{a:1,b:1}))8、如何实现一个只读属性
9、下面的代码输出什么?·
import {watch,reactive} from "vue"
const state = reactive({
a:1,
b:2,
c:3
})
watch(()=>{
console.log(state.a+state.b) // 输出两次3
return state.a+state.b
},
(val)=>{
console.log(val);
}
)
setTimeout(()=>{
state.a++;
state.b--;
})10、有哪些跨域方案?真实项目中如何选择?
cors
jsonp
代理
如何抉择 和生产环境保持一致即可11、下面说法正确的是
A. setTimeout(foo,0) 这行代码可以等价替换为foo()
B. 使用 Object.assign(obj1,obj2) 可以实现对象的浅拷贝
C. for...in 循环可以遍历对象自身及其原型链上的可枚举属性
D. Object.keys() 可以遍历出对象原型链上的属性
BC
Object.keys 对象自身可枚举的属性
12、如果一个包的代码所有工程都要使用,应该对它进行?
A. 本地安装 1
B. 全局安装
C. 本地安装和全局安装
D. 以上都可以
13、下面哪个不是常见衡量前端页面性能指标
A. 首字节加载时间 Time To First Byte TTFB
B. DomReady 时间
C. 页面完全加载时间
D. QPS (Queries Per Seconds)
D
14、如何理解this
函数里面的this指向 取决于函数的调用方式
通过`new method()`调用 那就是指向新对象
直接调用 `method()` 调用 全局对象
通过对象调用 `obj.method()` 前面的对象
通过call apply bind 函数调用 `method.call(ctx)` this指向第一个参数如果this在全局作用域中 那就要看环境 第一 如果是浏览器环境 this 指向window 如果是node环境 this指向一个空对象
15、什么叫BFC
16、CommonJs 和 ESModule 区别
标准来源
- CommonJs 社区标准(Node社区)
require新增API - ESM 官方标准
import新增语法
- CommonJs 社区标准(Node社区)
时态
- CommonJs 运行时态 运行时确定依赖关系
- ESM 运行时(
import()) , 编译时(静态)tree shake
17、http2有哪些升级
- 二进制分桢
- 多路复用
- 优先级
- 流式传输
- HTTP队头阻塞(由于多个请求使用的是同一个TCP连接,服务器必须按照请求到达的顺序进行响应)
- 头部压缩
- 服务器推
18、手写节流函数
function throttle(fn,wait){
let lastTime = null;
return function (...args){
const now = Date.now();
if(lastTime === null || now-lastTime>wait){
//技能之前没用过 或者 技能CD已好
fn.apply(this,args);
lastTime = now; // 更新技能释放时间
}
}
}
节流和防抖的区别
节流:再一段固定的时间内无论调用了多少次函数 我只运行一次 (回城)
防抖:一个请求在一段时间内没有再发起第二次相同请求的动作后开始执行 (技能CD)19、下面结果输出结果是?
const s = "123";
s.c = '4' // 由于s是一个原始类型 是不能属性的 只能创建临时实例 但是用完就被垃圾回收了
s.d = '5'// 由于s是一个原始类型 是不能属性的 只能创建临时实例 但是用完就被垃圾回收了
const [a,b] = s // 解构的是1,2
const [c,d] = s
console.log(a)
console.log(b)
console.log(c)
console.log(d)
//答案选D- A
undefinedundefinedundefinedundefined - B
undefinedundefined45 - C 1 2 4 5
- D 1 2
undefinedundefined - E 报错
20、在地址栏输入URL后按下回车,会发生哪些事?
- URL检测:纠错/补全
- DNS (寻找IP) (浏览器缓存)--> (本地host文件) --> (本机DNS服务器) --> (远程DNS服务器) --> (顶级域名服务器) --> (权威域名服务器) 找到
ip之后层层的缓存- 查找浏览器缓存有没有对应的IP映射
- 如果上面没有就查找本地
host文件有没有IP映射 - 如果上述也没有的话就查找本机的DNS服务器
- 如果还没有就接着查询远程DNS服务器
- 如果还没有顶级域名服务器
- 权威域名服务器
- TCP三次握手 (SSL加密)
- 准备请求(请求头:cookie + ...)
- 发送请求(GET)
- 服务器处理请求
- 服务器响应
- 浏览器收到响应头
- 处理响应头(set-cookie、contentType、缓存、状态码、connection:keep-alive)
- 收响应体
- 渲染(js引擎和渲染引擎)
- 解析 (资源加载 , 资源描述符)
- render树
- render layer树
- 栅格化
- files
- 合成-> IPC->GPU->绘制
- TCP四次挥手
21、哪些数据在堆上,哪些数据在栈上?
- 栈:变量,参数
- 堆:对象
22、什么是闭包?是否会造成内存泄露?
什么是闭包?
在一个函数环境中,闭包 = 函数 + 词法环境
var a = 1;
function m(){
}什么是内存泄漏呢?
持有了本该销毁的函数 , 造成其关联的词法环境无法销毁
- js
#example let handler = ()=>{ } dom.addEventListener("click",handler) dom.removeEventListener("click",handler) # 这个时候应该将handler 变量置空 当后多个函数共享词法环境时 , 可能导致词法环境膨胀 , 从而发生无法访问的但无法销毁的数据。
js#example function create(){ let big = 'xx'; let small = 'xx'; function s1(){ big } function s2(){ small } return s2 } #以上的情况就会造成 s1中的big无法被销毁 因为s2访问这个create函数中的共享词法环境 导致big无法销毁
23、何时发生重排?何时发生重绘?
重排:所有对布局树的更改,以及所有对布局树的读取,都会引发重排
更改,异步重排
dom.style.width = '200px'
dom.style.height = '200px'读取,同步的 , 如果不同步就有可能读的脏数据
dom.style.width= '0px'
dom.style.transition='0.5s'
dom.clientHeight;
dom.style.width = '100px'重绘:对所有非几何信息的读取所造成的可见样式的变化会引发重绘 颜色 或者 边框
24、下面为True的表达式
A. null instanceof Object
B. null === undefined
C. null == undefined
D. NaN == NaN
答案 C25、vue3模板中的ref的实现原理
<template>
<div ref="xxx">
</div>
</template>26、vue2中有$forceUpdate() 方法可以强制组件渲染 , 那Vue3 又该如何强制渲染组件呢?
答案:暂无
27、获取元素尺寸有多少种方式?它们有何区别?
dom.style.widthdom.style.heightstyle 里面写的啥就是啥Dom cssDOM树不会回流getComputedStyle(dom)计算后的样式 值为某个数值+‘px’offsetWidthscrollWidthclientWidth布局树中的信息 值为不带单位的数值 会计算padding border属性dom.getBoundingClientRect视觉尺寸 例如元素加一个一些transform 之后不会改变布局树
28、文件指纹是什么?在前端工程化中有何作用?
文件指纹:用hash或校验和生成的文件唯一标识
作用:更新缓存
29、如何判断一个属性是否存在?有哪些方案?
布尔判定 (问题很多 )
jsconst obj = { a:0 } if(obj.a){ console.log("存在") }else{ console.log("不存在") }undefined 判定
jsconst obj = { a:0 } if(obj.a!==undefined){ console.log("存在") }else{ console.log("不存在") }Object.keys()
jsObject.hasOwnProperty() Reflect.hasOwnProperty 判断属性是否是自有属性 判断不了原型上的属性
jsinReflect.has可以判断原型链上的属性
30、一道Promise面试题 下面代码输出什么?
new Promise((resolve,reject)=>{
reject(1)
console.log(2)
resolve(3)
console.log(4)
}).then((res)=>{console.log(res)})
.catch(res=>{console.log(res)})
try{
new Promise((resolve,reject)=>{
throw 6; // 在promise报错 不会影响主线程 只会讲该promise 状态变为拒绝
}).then(res=>{console.log(7)})
.catch(err=>{
console.log(8)
})
}catch(err){
console.log(err)
}
答案 2 4 1 831、当QPS(每秒的访问量)达到峰值时,该如何处理?
QPS , Queries Per Second 每秒访问量
- 缓存:本地缓存,服务器缓存,CDN预热
- 合并请求:雪碧图、....
- 延迟请求:懒加载、请求队列
- 用户体验:提示,loading...
服务器
- 扩容
- 数据库优化:sql优化,索引,读写分离
- 负载均衡
- 监控报警
32、如何实现一个精准的 setInterval
为什么不精确?
- 事件循环模型影响回调执行时机
- 4ms最小时间(嵌套5层以上后)
- 失活页面间隔会被强制调整为1s
解决方案?
- 根据·
performance.now通过时间调整间隔差 requestAnimationFrame不受失活页面影响,收很多其他因素影响webworker不受失活页面影响 ,不受渲染帧率的影响
33、用户登录前,如何确定ta是谁?web端
- uuid:全局唯一id 场景不严格
- 浏览器指纹
fingerprint.js(指纹浏览器)跨境电商 tiktok - ip地址
34、一道vue3中watchEffect 函数监听响应式数据
import {reactive,watchEffect} from "vue"
const user = reactive({
name:"jerry",
addr:{
p:'xx1',
c:'xx1'
}
})
watchEffect(()=>{
// 依赖关系 user.addr 收集
// 依赖关系 user.addr.p 收集
console.log(user.addr.p);
});
setTimeout(()=>{
user.name = 'xz122'
},10); // 不触发
setTimeout(()=>{
user.addr.c = 'x122'
},20);// 不触发
setTimeout(()=>{
user.addr.p = 'beijing'
},30);//打印
setTimeout(()=>{
user.addr = {
p:'jiangshu',
c:'suzhou'
}
},40);//打印35、什么是BFF? 他有什么用?
Backend For Frontend 后端为前端服务
一般来讲 BFF层都是前端再写 原因是 第一 前端比较清楚接口API 第二,前端最清楚界面要啥数据
36、vue2中的v-for 和 v-if 哪个优先级高,vue2和vue3分开介绍,并说明会产生什么后果?
- vue2 v-for优先
- vue3 v-if优先
- 后果:会存在心智负担,开发的时候要小心
37、什么是CSS原子化?优劣势是什么?
Atomic css CSS原子化 单一的类指代某一个样式 例如 w-200px
- 优势:开发效率极大的提高 , 复用性高
- 劣势:吃团队配置 , 可读性 , 打包体积(
uncss,purgeCss)
38、发现样式不生效时,该如何调试确定问题
39、如何遍历树结构的前序、中序、后序
40、什么是AST? 它在前端有哪些应用场景?
AST abstruct Sntax Tree 抽象语法树 ,用来表达源码的属性结构 (
acorn)
应用:
- 转换代码
- babel
- less,scss
- 构建工具
- 压缩和混淆
- 自定义
- 检查/格式代码
- Eslint
41、同一个URL地址,如何实现手机打开是移动端页面,电脑打开是Web页面
- 流体布局
- 媒体查询
- 服务器判断请求头
user-agent
42、浏览器如何知晓服务器传递资源的类型?JS代码,CSS代码,图片等资源类型等?
响应头中的
ContentType
43、如何用JS判断多行文本溢出位置?
// 找出文本溢出的位置
function excededIndex(str,options){
const div = document.createElement("div");
div.style.position = 'fixed';
div.style.visiblity = 'hidden';
div.style.width = options.width;
div.style.height = options.height;
div.style.overflow = 'hidden'
}使用div 将其样式设置为overflow:hidden 这样就可能会产生 offsetWidth scrollHeight 这几个元素布局的属性 可以利用这个布局属性来计算溢出的位置
44、Vue3 能否支持IE浏览器
Vue3用了Proxy Proxy 不支持降级因为 Proxy 为浏览器原生行为
45、Vue项目要中有哪些常见的优化手段?
- 路由懒加载,图片懒加载(loading='lazy')
- Supence
v-if和v-show- 打包优化手段
- 网络优化手段
- CDN
- 图片格式化 (webp)
- gzip
nginx 开启gzip - 请求合并 (由于浏览器对同一域名有并发请求数量的限制,通常为4个,可能产生请求排队和阻塞)
- GrafQL
- HTTP2
nginx 开启
- key
- computed
- 保持对象地址稳定
- keep-alive
- 延迟装载
- v-model.lazy 延迟双向绑定
- 冻结对象(vue2)
- 函数式组件,无状态组件
46、package.json 中的版本号 ~1.2.3和^1.2.3 有什么区别?
{
"dependencies":{
"vue":"^2.3.6"
}
}语义化版本控制
47、后端响应巨量数据,如何避免其性能问题?
虚拟DOM
48、请说说你对原型的理解
- 首先它是实现面向对象开发的核心机制之一 ,其次它主要用于实现属性共享和继承
49、页面上有100万个任务需要执行,如何保证页面不卡顿
requestAnimationFrame
requestIdCallback
webWorker
50、死循环会导致什么样的后果?无限递归会导致什么后果?
死循环:主线程卡死阻塞线程 界面无响应
无限递归: 栈溢出 , 程序报错
51、JS的作用域有哪些?
- 函数作用域
- 块级作用域
- 全局作用域
- 模块作用域
52、vue中如何解决组件循环依赖
vue2 使用 import 延迟导入
<template>
<div>1222</div>
</template>
<script>
export default{
components:{
//方法1 动态导入
comp:()=>import("./comp.vue").then(m=>m.default)
},
//方法2
beforeCreate(){
this.$options.components.comp = require("./comp.vue").default
}
}
</script>
方法3 就是将两个循环依赖的组件进行全局注册vue3
<template>
<div>
<button @click="loadComponent">加载组件</button>
<AsyncComponent v-if="isLoaded" />
</div>
</template>
<script setup>
import { ref } from 'vue';
import { defineAsyncComponent } from 'vue';
const isLoaded = ref(false);
const AsyncComponent = defineAsyncComponent(() => import('./MyAsyncComponent.vue'));
function loadComponent() {
isLoaded.value = true;
}
</script>53、Vue组件通信
- 父子组件通信
单向数据流ref+defineExpose 直接调用子组件方法 - 兄弟组件通信
mitt共享父组件的状态 - 跨层级组件通信
provide + inject 祖孙组件数据传递 - 其他方案
Vuex/piniaLocalStoragewindow全局对象ES Module import 常量数据共享
54、为什么需要虚拟DOM?
结论是开发效高
- 框架设计:就是数据驱动所以需要构建一个虚拟DOM对象,就拿
vue举例 如果组件中的对应的数据变化我的组件就得重来一遍 , 所以vue也做了一些优化手法例如diff算法等等 - 跨平台(运行时解耦):虚拟DOM 就是描述UI的
js对象也就是说 , 如果在web页面端 ,我可以根据虚拟DOM生成响应的真实DOM , 在移动端也可以根据虚拟DOM 去生成相应的原生组件 这样就可以完全和运行时解耦 和环境解耦 从而保证这套框架可以移植到任何环境
55、前端上传文件的方式
使用Base64
js// 请求路径 /upload/single // 请求方法 POST // 消息格式使用formData
bash# 请求路径 /upload/single # 请求方法 POST # 消息格式 multipart/form-data使用纯二进制格式
单文件
# 请求路径 /upload/binary
# 请求方法 POST
# 消息格式 (application/octet-stream)
# 消息头:x-ext 文件的后缀名
fetch('/upload', {
method: 'POST',
headers: {
'Content-Type': 'application/octet-stream',
'x-ext':'jpg'
},
body: yourBinaryBlob // Blob 或 ArrayBuffer
});一次多文件
const files = [file1, file2]; // File 或 Blob 数组
const boundary = '---MY-BOUNDARY---';
// 自定义分隔内容
const parts = [];
for (const file of files) {
parts.push(new TextEncoder().encode(boundary));
parts.push(await file.arrayBuffer()); // 或 file.stream() if you want
}
parts.push(new TextEncoder().encode(boundary + '--'));
const total = new Blob(parts);
fetch('/upload-multiple', {
method: 'POST',
headers: {
'Content-Type': 'application/octet-stream',
'x-ext':'jpg'
},
body: total
});
//nodejs
app.use(express.json({ limit: '50mb' }));
app.post('/upload-multiple', (req, res) => {
const files = req.body;
for (const file of files) {
const buffer = Buffer.from(file.data, 'base64');
fs.writeFileSync(`uploads/${file.name}`, buffer);
}
res.send('All files uploaded');
});56、项目中SEO如何做?
57、uniapp生命周期执行顺序
- 不包含组件的页面
onLoad>onShow>onReady
- 包含组件的页面
onLoad>onShow>onBeforeMount>onReady>onMounted
58、SSR 和 CSR 区别?
SSR (server slide render) 服务端渲染
- 优点
- 更快的首屏渲染
- SEO友好
- 缺点
- 服务器压力比较大
- 开发部署复杂
- SSR返回静态HTML后,后续页面的动态交互需要在客户端使用 JavaScript 接管
- 优点
CSR (client slide render) 客户端渲染
- 优点
- 更强的前端交互性与动态性
- 前后端分离
- 减轻服务器端负载
- 缺点
- 首屏渲染速度慢
- SEO不友好
- 复杂的前端工程化
- 优点
59、inline和inline-block 之间有什么区别
- inline
- 不会独占一行
- 水平排列
- 不能设置宽高
- 默认基线对齐
- inline-block
- 不会独占一行
- 水平排列
- 可以设置宽高
60、nth-of-type 和 nth-child 有什么区别?
nth-child(n)
- 选择第
n个元素n是 从1开始的序号
- 选择第
nth-of-type( n )
- 选择第
n个同类型的元素
- 选择第
61、js中有哪些数据类型
- undefined
- Null
- Boolean
- String
- Symbol
- Number
- number
- bigint
- Object