likes
comments
collection
share

(58同城)面了一个半小时,嗓子都面哑了,转手就给我挂了???

作者站长头像
站长
· 阅读数 62

前言

总之一句话,聊了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

  • 垂直居中

    1. 利用 line-height 实现居中,这种方法适合纯文字类
    2. 通过设置父容器 相对定位 ,子级设置 绝对定位,标签通过margin实现自适应居中
    3. 弹性布局 flex :父级设置display: flex; 子级设置margin为auto实现自适应居中
    4. 父级设置相对定位,子级设置绝对定位,并且通过位移 transform 实现
    5. 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 的域属性来实现不同域之间的共享。

当设置 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 中进行了调用,这样实现了跨域。

步骤:

  1. 去创建一个script标签
  2. script的src属性设置接口地址
  3. 接口参数,必须要带一个自定义函数名,要不然后台无法返回数据
  4. 通过定义函数名去接受返回的数据
//动态创建 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) 功能,能够实时更新修改的代码,无需手动刷新页面。其原理主要包括以下几个方面:

  1. 监听文件变化:webpack-dev-server 会监听项目中文件的变化,一旦文件发生改变,它会立即重新编译打包。
  2. 使用内存中的文件:webpack-dev-server 将编译后的文件存储在内存中,而不是写入磁盘。这样可以大大提高访问速度,特别是在开发阶段频繁修改文件时。
  3. 实时更新:webpack-dev-server 支持 Hot Module Replacement (HMR),即模块热替换。当文件发生改变时,它会将变更的模块部分替换掉旧的模块,而不会刷新整个页面,从而实现了实时更新的效果。
  4. 提供 HTTP 服务:webpack-dev-server 启动一个 HTTP 服务器,用于提供静态文件和编译后的资源。默认情况下,它监听在 localhost 的一个端口上。
  5. 支持代理: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. 图片懒加载怎么实现?图片预加载的方案有了解过吗?怎么做?

图片的加载包含了图片的请求和渲染

  1. 直接v-if,如果达到了展示区域,则展示(这种比较简单粗暴点)。
  2. 使用data-xxx属性,把图片的连接复制给该属性,当达到该区域时,获取该该属性中的图片链接,并把该链接复制给src属性。
  3. 同上,不过用的不是容器属性,而是 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就是根据用户位置分配最近的资源。

(58同城)面了一个半小时,嗓子都面哑了,转手就给我挂了???CDN 工作原理

在没有 CDN 时,我们使用域名访问一个站点的路径为:用户提交域名 -> 浏览器对域名进行解析 -> DNS 解析得到目的主机的 IP 地址 -> 根据 IP 地址发出请求 -> 得到请求数据并回复。 使用 CDN 后,DNS 返回的不再是一个 IP 地址,而是一个 CName(Canonical Name)别名记录,指向 CDN 的全局负载均衡。

(58同城)面了一个半小时,嗓子都面哑了,转手就给我挂了???
  1. 当用户在浏览器上输入 URL 时,经过本地 DNS 系统解析,DNS 系统会最终将域名的解析权交给 CNAME 指向的 CDN 专用 DNS 服务器;
  2. CDN 专用 DNS 服务器将 CDN 全局负载均衡设备的 IP 地址返回给用户;
  3. 用户向 CDN 全局负载均衡设备发起内容 URL 访问请求;
  4. CDN 全局负载均衡设备根据用户 IP 地址以及用户请求的内容 URL,选择一台用户所属区域的 CDN 区域负载均衡设备,告诉用户向这台设备发起请求;
  5. CDN 区域负载均衡设备会为用户选择一台合适的缓存服务器提供服务,然后 CDN 区域负载均衡设备会向全局负载均衡设备返回一台缓存服务器的 IP 地址(选择的依据包括:根据用户 IP 地址,判断哪一台服务器距用户最近;根据用户所请求的 URL 中携带的内容名称,判断哪一台服务器上有用户所需内容;查询各个服务器当前的负载情况,判断哪一台服务器尚有负载能力等等);
  6. 全局负载均衡设备把缓存服务器的 IP 地址返回给用户;
  7. 用户向缓存服务器发起请求,缓存服务器响应用户请求,将用户所需内容返回给用户。如果这台缓存服务器上没有用户想要的内容,而区域负载均衡设备依然将它分配给了用户,那么这台缓存服务器就需要向它的上一层缓存服务器请求内容,直至追溯到网站的源服务器将内容拉回到本地。

22. 静态资源的部署会走CDN策略吗?如果我源站有一些静态资源更新,它是怎么做到 CDN 服务器的更新?

静态资源的部署通常会使用 CDN 策略,以加快内容传输速度、减少源站服务器的负载并提高网站的性能和可用性。CDN(内容分发网络)通过将静态资源(如图片、CSS、JavaScript 文件等)缓存到全球各地的边缘节点服务器上,实现内容的快速分发。

更新CDN缓存的方法

  1. 刷新全站缓存

    当网站进行大规模更新时,可以选择刷新全站CDN缓存。这样可以确保所有的缓存内容都被更新,用户可以看到最新的内容。这种方法会耗费较多的时间和资源,

  2. 刷新指定缓存

    如果只需要更新部分页面或资源,可以选择刷新指定的CDN缓存。这通常通过在网站后台管理系统中的CDN管理界面进行操作。根据CDN服务商的不同,可能提供刷新单个文件、文件夹或者URL的功能。选择需要更新的文件或URL,点击刷新按钮即可。

  3. 自动更新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;
};
(58同城)面了一个半小时,嗓子都面哑了,转手就给我挂了???

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;
}
(58同城)面了一个半小时,嗓子都面哑了,转手就给我挂了???

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;
}
(58同城)面了一个半小时,嗓子都面哑了,转手就给我挂了???

filter去重

//filter去重
const handleRemoveRepeat = (arr) => arr.filter((item,index) => arr.indexOf(item,0) === index);
(58同城)面了一个半小时,嗓子都面哑了,转手就给我挂了???

ES6的Set去重

    const arr = [1,1,2,2,3,3,4,4,5,5];
    const setData = Array.from(new Set(arr));
    console.log(setData);

(58同城)面了一个半小时,嗓子都面哑了,转手就给我挂了???

27.(手撕)防抖节流,然后防抖之后的变体需要有个立即触发的参数(第一次立即执行,后续才需要防抖)

常规体

function debounce(func, delay) {
    let timer;
    return function (...args) {
        let that = this;
        clearTimeout(timer);
        timer = setTimeout(function () {
            func.apply(that, args)
        }, delay)
    }
}

变体(根据防抖的触发)

(58同城)面了一个半小时,嗓子都面哑了,转手就给我挂了???
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. 实习项目中挑一个收获比较大或者有亮点的?或者支持需求功能的时候有没有什么难点?怎么解决的?

这里需要根据自己的经历提前准备好了,以防被问到没回答好

  1. axios的封装
  2. 手写功能函数,比如表单的失焦和聚焦(保存功能),表单数据的变动
  3. 国际化多语言,文件上传下载和数据的处理,webworker的实际应用
  4. SSO单点登录的理解
  5. iframe框架的实际应用

29. 职业性规划

夯实基础、每日算法、学习源码、系统学习、部署项目、AIGC

30. 反问

  1. 工作氛围

  2. 产品从提出到上线的大概人员分配情况

  3. 业务线

  4. 技术栈

结语

这是之4月份面试之后写得部分草稿,由于一直没时间就丢到草稿箱里没整理,这会儿才整理出来,后续应该还有一些,如果有空的话,嘿嘿~。

转载自:https://juejin.cn/post/7379958792723808275
评论
请登录