(58同城)面了一个半小时,嗓子都面哑了,转手就给我挂了???
前言
总之一句话,聊了N久,从了解情况,八股,手撕代码,最后的项目,太多了(就两道比较简单算法和手写,中途讲得口干得受不猛灌了口水)。面完后看了牛客上的帖子,发现有几个说面完就挂了,此时我心里有点慌了,但基本都答出来的我怎么可能会挂,然后按捺不住内心去官网看了,真给我挂了,诶~不是,都聊了这么久了不给个机会?我心疼你的时间啊面试官giegie。。。不过人是真好,面试过程中我提出的疑惑都会解答,整场面试和技术交流一样,也不亏就是了。
1. 个人介绍加各种了解情况
先个人自我介绍,然后base地北京是否ok?实习经历是否学校安排?为什么会换实习单位?专业分方向?为什么选择前端?
2. 样式选择器的优先级
选择器
- id选择器(#myid)
- 类选择器(.myclass)
- 属性选择器(a[rel="external"])
- 伪类选择器(a:hover, li:nth-child)
- 标签选择器(div, h1,p)
- 相邻选择器(h1 + p)
- 子选择器(ul > li)
- 后代选择器(li a)
- 通配符选择器(*)
优先级:
!important
- 内联样式(1000)
- ID选择器(0100)
- 类选择器/属性选择器/伪类选择器(0010)
- 元素选择器/伪元素选择器(0001)
- 关系选择器/通配符选择器(0000)
带!important 标记的样式属性优先级最高; 样式表的来源相同时:!important > 行内样式>ID选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性
3. 水平垂直居中
-
水平居中
-
对于 行内元素 :
text-align: center
; -
对于确定宽度的块级元素:
(1)width和margin实现。
margin: 0 auto
;(2)绝对定位和margin-left: (父width - 子width)/2, 前提是父元素position: relative
-
对于宽度未知的块级元素
(1)
table标签配合margin左右auto实现水平居中
。使用table标签(或直接将块级元素设值为 display:table),再通过给该标签添加左右margin为auto。(2)inline-block实现水平居中方法。display:inline-block和text-align:center实现水平居中。
(3)
绝对定位+transform
,translateX可以移动本身元素的50%。(4)flex布局使用
justify-content:center
-
-
垂直居中
- 利用
line-height
实现居中,这种方法适合纯文字类 - 通过设置父容器 相对定位 ,子级设置
绝对定位
,标签通过margin实现自适应居中 - 弹性布局 flex :父级设置display: flex; 子级设置margin为auto实现自适应居中
- 父级设置相对定位,子级设置绝对定位,并且通过位移 transform 实现
table 布局
,父级通过转换成表格形式,然后子级设置 vertical-align 实现
。(需要注意的是:vertical-align: middle使用的前提条件是内联元素以及display值为table-cell的元素)。
- 利用
4. cookie、localStorage、sessionStorage的区别
相同点:
- 存储在客户端
不同点:
- cookie数据大小不能超过4k;sessionStorage和localStorage的存储比cookie大得多,可以达到5M+
- cookie设置的过期时间之前一直有效;localStorage永久存储,浏览器关闭后数据不丢失除非主动删除数据;sessionStorage数据在当前浏览器窗口关闭后自动删除
- cookie的数据会自动的传递到服务器;sessionStorage和localStorage数据保存在本地
5. 后端服务可以修改cookie的值吗?前端可以修改cookie的值吗?
前后端都可以修改cookie,通常先是由后端生成 cookie 值,这其中携带了用户信息等基本信息,然后前端根据需要会把一些信息添加到 cookie 中,并随着请求携带传给后端,后端拿到后再进行相应修改或者直接用。
6. 前端登录的时效性怎么通过cookie做的?
一般是后端设置cookie的时效性
Session
如果Cookie的有效期为Session,类似于sessionStorge一样,即关闭浏览器就失效。
Expires
指定具体的失效时间,格式大致为2025-02-17T04:44:56.921Z
,即到2025年2月17日4点44分56秒921毫秒
失效
Max-Age
从拿到 Cookie 后开始倒计时设置 的Max-Age的值。例如Max-age=3000
。当获取到该Cookie后开始倒计时,3000秒之后便失效。
7. 有一个 a.58.com 和 b.58.com,这两个不同域中分别在locaStorage中存储值能共享吗?
localStorage 是基于同源策略的,因此不同域名的 localStorage 之间是不能直接共享数据的。即使是同一域名下的不同子域名,比如 a.58.com 和 b.58.com,它们之间的 localStorage 也是相互独立的,无法直接共享数据。
然而,如果这些域名拥有相同的顶级域名(比如都是 ".58.com"),浏览器将会认为它们是同一来源,因此它们之间的同源策略就不再适用。这样一来,不同子域名之间的页面就可以共享 localStorage 数据了。
要实现这一点,你可以在DNS服务器设置中将不同的子域名都指向相同的顶级域名。通常,这是通过在 DNS 记录中配置 CNAME 记录或 A 记录来完成的。
8. cookie 可以实现不同域共享吗?
在默认情况下,Cookie 是受同源策略限制的,因此不同域之间的 Cookie 不能直接共享。同源策略要求 cookie 的域名必须完全相同(包括子域名),否则浏览器不会发送这个 cookie。
但是,可以通过设置 Cookie 的域属性来实现不同域之间的共享。
Set-Cookie: name=value; domain=.58.com; path=/
当设置 Cookie 时,可以通过指定域属性来指定哪些域名可以访问这个 Cookie。如果指定的是顶级域名,那么所有的子域名都可以访问这个 Cookie。例如上述中,如果你在顶级域名 ".58.com" 设置了一个 Cookie,并将域属性 domain 设置为 ".58.com",那么所有以 ".58.com" 结尾的子域名(比如 a.58.com、b.58.com、xxx.58.com 等)都可以访问这个 Cookie。
9. 浏览器为什么会有跨域问题?
浏览器本身的同源策略等一些跨域限制造成的,为了保护用户的数据安全和隐私,防止恶意网站获取用户的敏感信息或进行 CSRF(跨站请求伪造)等攻击。虽然跨域限制会给开发带来一些挑战,但它是保护用户安全的必要手段。
10. 跨域解决办法(这里我表现欲强了点,回答完上一个问题后反问面试官需要说说跨域的解决办法吗?作死啊我)
11. jsonp的原理?
ajax 请求受同源策略影响,不允许进行跨域请求,而 script 标签 src 属性中的链 接却可以访问跨域的 js 脚本,利用这个特性,服务端不再返回 JSON 格式的数据,而是 返回一段调用某个函数的 js 代码,在 src 中进行了调用,这样实现了跨域。
步骤:
- 去创建一个script标签
- script的src属性设置接口地址
- 接口参数,必须要带一个自定义函数名,要不然后台无法返回数据
- 通过定义函数名去接受返回的数据
//动态创建 script
var script = document.createElement('script');
// 设置回调函数
function getData(data) {
console.log(data);
}
//设置 script 的 src 属性,并设置请求地址
script.src = 'http://localhost:3000/?callback=getData';
// 让 script 生效
document.body.appendChild(script);
JSONP 的缺点: JSON 只支持 get,因为 script 标签只能使用 get 请求; JSONP 需要后端配合返回指定格式的数据。
12. 如果把 script 标签换成图片标签,可以实现跨域请求吗?
脑子当时想的是把scr的回调链接换成图片链接,没注意到是换了标签
JSONP利用 <script>
标签的src属性可以跨域加载资源的特性,来实现跨域请求的方法。当浏览器遇到 <script>
标签时,会像加载JavaScript脚本一样去请求资源,并且不受同源策略的限制。
但是,如果把 <script>
标签换成 <img>
标签,就不能实现跨域请求了。原因是<img>
标签的src属性加载的是图片资源,而浏览器不会将返回的图片数据当作JavaScript来执行,因此无法实现跨域请求。
13. get 请求和 post 的请求有什么区别吗?
14. 前端本地开发的跨域解决以及实践原理?
webpack-dev-server,它是一个为了开发体验而在本地构建的小型 Express 服务器(想了解更多的话可以看看它的源码)。它使用了 Webpack 的 Hot Module Replacement (HMR) 功能,能够实时更新修改的代码,无需手动刷新页面。其原理主要包括以下几个方面:
- 监听文件变化:webpack-dev-server 会监听项目中文件的变化,一旦文件发生改变,它会立即重新编译打包。
- 使用内存中的文件:webpack-dev-server 将编译后的文件存储在内存中,而不是写入磁盘。这样可以大大提高访问速度,特别是在开发阶段频繁修改文件时。
- 实时更新:webpack-dev-server 支持 Hot Module Replacement (HMR),即模块热替换。当文件发生改变时,它会将变更的模块部分替换掉旧的模块,而不会刷新整个页面,从而实现了实时更新的效果。
- 提供 HTTP 服务:webpack-dev-server 启动一个 HTTP 服务器,用于提供静态文件和编译后的资源。默认情况下,它监听在 localhost 的一个端口上。
- 支持代理:webpack-dev-server 支持配置代理,可以将特定的 URL 请求代理到另一个服务器上,解决跨域请求的问题。
15. 移动端适配(我一股脑的说出来了,然后反问你想听哪种,giao,再次作死)
-
方案一:百分比设置(不推荐)
- 因为不同属性的百分比值,相对的可能是不同参照物,所以百分比往往很难统一
- 所以百分比在移动端适配中使用是非常少的
-
方案二:rem单位+动态html的font-size
- 媒体查询
- 动态改写font-size,编写js代码
-
方案三:vw单位(推荐)
-
方案四:flex的弹性布局
16. UI设计稿有个 750 的这种尺寸的 PX 值,我们要给它做这种移动端设备,需要把它转成这个REM,这种有什么方式吗?
一开始以为是用 rem 来做适配,在沟通交流才理解问得是 px 转 rem
less 或者 sass 预编译中写一个 css 混合函数
17. 有没有一种自动化的转换的方式,在最终输出的样式里边怎么把 px 比如说转成一个 REM 的这种单位方式?
vscode中有相关的插件可以使用,让 px 自动转化成你想要的 rem,其中 px 和 rem 的转化比例可以自己手动调整。
18. 箭头函数有什么特点?可以用箭头函数创造实例吗?
19. 做过的项目或者了解的性能优化问题?
20. 图片懒加载怎么实现?图片预加载的方案有了解过吗?怎么做?
图片的加载包含了图片的请求和渲染
- 直接v-if,如果达到了展示区域,则展示(这种比较简单粗暴点)。
- 使用data-xxx属性,把图片的连接复制给该属性,当达到该区域时,获取该该属性中的图片链接,并把该链接复制给src属性。
- 同上,不过用的不是容器属性,而是
IntersectionObserver
API。
// 方法1
<template>
<div ref="imageContainer" v-if="isInViewport">
<img :src="imageSrc" alt="Lazy Loaded Image">
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const isInViewport = ref(false);
const imageSrc = ref('path/to/your/image.jpg');
const imageContainer = ref(null);
// 检查图片容器是否在视口内的方法
const checkInView = () => {
if (imageContainer.value) {
// 获取图片容器的边界矩形
const rect = imageContainer.value.getBoundingClientRect();
// 如果图片容器的顶部在视口内,并且底部也在视口内,则设置为 true
if (rect.top < window.innerHeight && rect.bottom > 0) {
isInViewport.value = true;
}
}
};
onMounted(() => {
// 初始化检查
checkInView();
// 监听滚动事件,滚动时检查
window.addEventListener('scroll', checkInView);
});
</script>
// 方法2
<template>
<img :data-src="imageSrc" ref="lazyImage" alt="Lazy Loaded Image">
</template>
<script setup>
import { ref, onMounted } from 'vue';
const imageSrc = ref('path/to/your/image.jpg');
const lazyImage = ref(null);
// 懒加载方法
const lazyLoad = () => {
if (lazyImage.value) {
// 获取图片容器的边界矩形
const rect = lazyImage.value.getBoundingClientRect();
// 如果图片容器的顶部在视口内,并且底部也在视口内,则加载图片
if (rect.top < window.innerHeight && rect.bottom > 0 && !lazyImage.value.src) {
lazyImage.value.src = lazyImage.value.dataset.src;
lazyImage.value.removeAttribute('data-src');
}
}
};
onMounted(() => {
// 初始化懒加载
lazyLoad();
// 监听滚动事件,滚动时执行懒加载
window.addEventListener('scroll', lazyLoad);
});
</script>
// 方法3
<template>
<img :data-src="imageSrc" ref="lazyImage" alt="Lazy Loaded Image">
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
const imageSrc = ref('path/to/your/image.jpg');
const lazyImage = ref(null);
onMounted(() => {
// 创建一个 IntersectionObserver 实例
const observer = new IntersectionObserver((entries, self) => {
entries.forEach(entry => {
// 如果图片容器进入视口,`isIntersecting` 类似于容器高宽判断
if (entry.isIntersecting) {
const img = entry.target;
// 设置图片的 src 属性,并移除 data-src 属性
img.src = img.dataset.src;
img.removeAttribute('data-src');
// 停止观察当前图片容器
self.unobserve(img);
}
});
});
// 观察当前图片容器
if (lazyImage.value) {
observer.observe(lazyImage.value);
}
// 组件卸载时,停止观察
onUnmounted(() => {
if (lazyImage.value) {
observer.unobserve(lazyImage.value);
}
});
});
</script>
21. 你实习期间前端代码打包之后,是上传到同一个域名,还是会做一些 CDN 的策略?有了解过 CDN 策略吗?
前端代码打包之后,是上传到同一个域名,该域名是统一的测试容器,即测试环境。
CDN(内容分发网络,Content Delivery/Distribut Nectwork),是建立并覆盖在承载网之上,由分配在不同区域的边缘节点服务器群组成的分布式网络。
CDN 加速的本质是缓存加速。将服务器上存储的静态内容缓存到 CDN 节点上,当访问这些静态内容时,无需访问服务器源站,就近访问 CDN 节点即可获取相同内容,从而达到加速的效果,同时减轻服务器源站的压力。 简单来说,CDN就是根据用户位置分配最近的资源。
CDN 工作原理
在没有 CDN 时,我们使用域名访问一个站点的路径为:用户提交域名 -> 浏览器对域名进行解析 -> DNS 解析得到目的主机的 IP 地址 -> 根据 IP 地址发出请求 -> 得到请求数据并回复。 使用 CDN 后,DNS 返回的不再是一个 IP 地址,而是一个 CName(Canonical Name)别名记录,指向 CDN 的全局负载均衡。

- 当用户在浏览器上输入 URL 时,经过本地 DNS 系统解析,DNS 系统会最终将域名的解析权交给 CNAME 指向的 CDN 专用 DNS 服务器;
- CDN 专用 DNS 服务器将 CDN 全局负载均衡设备的 IP 地址返回给用户;
- 用户向 CDN 全局负载均衡设备发起内容 URL 访问请求;
- CDN 全局负载均衡设备根据用户 IP 地址以及用户请求的内容 URL,选择一台用户所属区域的 CDN 区域负载均衡设备,告诉用户向这台设备发起请求;
- CDN 区域负载均衡设备会为用户选择一台合适的缓存服务器提供服务,然后 CDN 区域负载均衡设备会向全局负载均衡设备返回一台缓存服务器的 IP 地址(选择的依据包括:根据用户 IP 地址,判断哪一台服务器距用户最近;根据用户所请求的 URL 中携带的内容名称,判断哪一台服务器上有用户所需内容;查询各个服务器当前的负载情况,判断哪一台服务器尚有负载能力等等);
- 全局负载均衡设备把缓存服务器的 IP 地址返回给用户;
- 用户向缓存服务器发起请求,缓存服务器响应用户请求,将用户所需内容返回给用户。如果这台缓存服务器上没有用户想要的内容,而区域负载均衡设备依然将它分配给了用户,那么这台缓存服务器就需要向它的上一层缓存服务器请求内容,直至追溯到网站的源服务器将内容拉回到本地。
22. 静态资源的部署会走CDN策略吗?如果我源站有一些静态资源更新,它是怎么做到 CDN 服务器的更新?
静态资源的部署通常会使用 CDN 策略,以加快内容传输速度、减少源站服务器的负载并提高网站的性能和可用性。CDN(内容分发网络)通过将静态资源(如图片、CSS、JavaScript 文件等)缓存到全球各地的边缘节点服务器上,实现内容的快速分发。
更新CDN缓存的方法
-
刷新全站缓存
当网站进行大规模更新时,可以选择刷新全站CDN缓存。这样可以确保所有的缓存内容都被更新,用户可以看到最新的内容。这种方法会耗费较多的时间和资源,
-
刷新指定缓存
如果只需要更新部分页面或资源,可以选择刷新指定的CDN缓存。这通常通过在网站后台管理系统中的CDN管理界面进行操作。根据CDN服务商的不同,可能提供刷新单个文件、文件夹或者URL的功能。选择需要更新的文件或URL,点击刷新按钮即可。
-
自动更新CDN缓存
有些网站更新频率较高,为了节省人工操作的时间和精力,可以选择自动更新CDN缓存的方法。这可以通过使用CDN服务商提供的API接口或者配置自动更新脚本来实现。
23. vue2 和 vue3 的区别?
24. 为什么vue的响应式迭代需要由 defineProtety 变成 proxy
25. nextTick 函数有什么作用或者使用场景?
26. (算法)去重数组
双重循环去重
//双重循环去重
const handleRemoveRepeat = (arr) => {
for (let i=0,len = arr.length; i < len; i++) {
for (let j = i + 1; j < len; j++) {
if (arr[i] === arr[j]) {
arr.splice(j, 1);
j--;
len--;
}
}
}
return arr;
};

indexOf去重
//indexOf去重去重
const handleRemoveRepeat = (arr) => {
let repeatArr = [];
for (let i = 0,len = arr.length ; i < len; i++)
if (repeatArr.indexOf(arr[i]) === -1) repeatArr.push(arr[i])
return repeatArr;
}

includes去重
// includes去重
const handleRemoveRepeat = (arr) => {
let repeatArr = [];
for (let i = 0,len = arr.length ; i < len; i++)
if (!repeatArr.includes(arr[i])) repeatArr.push(arr[i])
return repeatArr;
}

filter去重
//filter去重
const handleRemoveRepeat = (arr) => arr.filter((item,index) => arr.indexOf(item,0) === index);

ES6的Set去重
const arr = [1,1,2,2,3,3,4,4,5,5];
const setData = Array.from(new Set(arr));
console.log(setData);
27.(手撕)防抖节流,然后防抖之后的变体需要有个立即触发的参数(第一次立即执行,后续才需要防抖)
常规体
function debounce(func, delay) {
let timer;
return function (...args) {
let that = this;
clearTimeout(timer);
timer = setTimeout(function () {
func.apply(that, args)
}, delay)
}
}
变体(根据防抖的触发)

function debounce(func, delay, imd) {
let timer;
return function (...args) {
let that = this;
if (imd && !timer) {
func.apply(this);
}
clearTimeout(timer);
timer = setTimeout(function () {
func.apply(that, args)
}, delay)
}
}
28. 实习项目中挑一个收获比较大或者有亮点的?或者支持需求功能的时候有没有什么难点?怎么解决的?
这里需要根据自己的经历提前准备好了,以防被问到没回答好
- axios的封装
- 手写功能函数,比如表单的失焦和聚焦(保存功能),表单数据的变动
- 国际化多语言,文件上传下载和数据的处理,webworker的实际应用
- SSO单点登录的理解
- iframe框架的实际应用
29. 职业性规划
夯实基础、每日算法、学习源码、系统学习、部署项目、AIGC
30. 反问
-
工作氛围
-
产品从提出到上线的大概人员分配情况
-
业务线
-
技术栈
结语
这是之4月份面试之后写得部分草稿,由于一直没时间就丢到草稿箱里没整理,这会儿才整理出来,后续应该还有一些,如果有空的话,嘿嘿~。
转载自:https://juejin.cn/post/7379958792723808275