前端场景面试题

回答流程化

  1. 交代背景
  2. 研究方案
  3. 方案落地
  4. 反思

问题一:js超过Number最大值的数怎么处理?

背景:

大数据的计算:金融、科学计算、数据分析

格式展示

用户输入

解决方案:

BigInt

decimal.js

big.js

总结:

bigint来处理大数据

decimal来处理

格式化,格式化成用户好读的格式

表单校验

问题二:如何解决页面请求接口大规模并发问题?

滑动窗口算法,是专门来控制流量的。

背景:

数据采集平台,低代码编辑平台,有序相对稳定发送到后端。

研究方案:

1.请求队列

class RequestQueue{
  constructor(maxConcurrent){
    this.maxConcurrent = maxConcurrent; //最大并发请求数
    this.currentConcurrent = 0; //当前并发请求数
    this.queue = []; //请求队列
  }

  add(request){
    return new Promise(resolve,reject) => {
      this.queue.push({request,resolve,reject});
      this.processQueue();
    }
  }

  processQueue(){
    if(this.queue.length > 0 && this.curentConcurrent < this.maxConcurrent){
      const {request,resolve,reject} = this.queue.shift();
      this.currentConcurrennt++;
      request()
        .then(request)
        .catch(reject)
        .finally(()=>{
          this.currentConcurrent--;
          this.processQueue()'
        });
    }
  }
}

//示例请求函数
function fetchData(url) {
  return fetch(url).then(response => response.json());
}

//使用请求队列
const requestqueue = new RequestQueue(5);

const urls = [
  '  ';
  '  '; 
]

const requests = urls.map(url => () => fetchData(url));

Promise.all(requests.map(request => requestQueue.add(request)))
  .then(results => {
    console.log('所有请求完成',results);
  })
  .catch(error => {
    console.error('请求失败',error);
  });


2.防抖/节流

--防抖(Debounce):确保在指定时间内函数只执行一次,一般取最后一次,常用于输入框的搜索建议。

function Debounce (fun, wait){
  let timeout;
  return function(...args){
    clearTimeout(timeout);
    timeout = setTimeout(()=>{
      func.apply(this,args);
    },wait);
  } 
}

--节流(Throttle):确保在指定时间间隔内函数执行一次,一般取第一次,常用于窗口的resize,scroll事件。

function throttle(func,limit){
  let inThrottle;
  return function(...args){
    if(!inThrottle){
      func.apply(this,args);
      inThrottle = true;
      setTimeout(()=>inThrottle = false,limit);
    }
  };
}

3.分页加载

落地、反思:

1.大数据量请求场景下,我们选用了请求队列,我主导封装了请求队列

2.防抖节流,用户交互层面上去解决减少请求的处理

3.分页,滚动加载,可视区绘制。

问题三:请说说大文件上传

背景:之前做xxx产品,我们会涉及到用户自定xxx文件上传。

经常遇到的一些问题:

--网络断开之后,之前传的没了。

--传着传着,网络波动,结果啥都没了。

--关机了,想接着传,做不到。

专业术语:

--断点续传

--断开重连重传

--切片上传

方案:

1.前端切片

2.将切片传递给后端,切片要取名:hash,index

3.后端组合切片

给面试官加料:

--前端切片:主线程做卡顿,web-worker多线程切片,处理完之后交给主进程发送。

--切完后,将blob存储到indexedDB,下次用户进来之后,嗅探一下是否存在未完成上传的切片,有就尝试继续上传。

--websocket,实时通知和请求序列的控制。

--整体说一说我主导这个大文件上传器整体设计:组件设计、props、事件、状态、拖拽上传、多文件选择、通用化不同文件的上传,上传统一协议。

const CHUNCK_SIZE = 5*1024*1024'; //每块大小为5MB

function uploadFile(){
  const file = document.getElementById('fileInput').files[0];
  if(!file){
    alert('Please select a file.');
  }

  const tatalChuncks = Math.ceil(file.size / CHUNK_SIZE);
  let currrentChunk = 0;

  function uploadChunck(){
    if(currentChunck >= totalChunks){
      console.log('upload complete');
      return;
    }
    
    const start = currentChunck *CHUNK_SIZE;
    const end = Math.min(start + CHUNK_SIZE,file.size);
    const chunk = file.silce(start,end);

    const formData = new FormData():
    formData.append('file',chunk);
    formData.append('chunkNumber',currentChunk+1);
    formData.append('totalChunks',totalChunks);

    fetch('/upload',{ 
      method:'POST';
      body:formData
    }).then(response => {
         if(response.ok){
          curentChunk++;
          uploadChunk();
         }else{console.error('Chunk upload faild')};
       )}.catch(
            error =>{console.error('Upload error',error)}
          );
  uploadChunk():
}

问题四:在前端怎么实现网页截图

背景:

飞书文档,内容在列表页想要查看

内容导出为png

设计类软件,出图

方案:

截图:

1.canvas

2.puppeteer

3.html2canvas

上传CDN

全页面截图/区域截图/特定区域截图

落地:

--截图工具的时候,需要考虑通用性,‘selector’

--设计具体协议

function takeScreenshot(){
  const element = document.getElementById('screenshot-target');
  html2canvas(element).then(canvas => {
    const img = canvas.toDataUrl('image/png');
    const link = document.createElement('a');
    link.ref = img;
    link.download = 'screenshot.png';
    link.click();
  });
}

问题五:移动端适配问题如何解决

背景:

项目像支持PC、移动端。

方案:

1.根据不同端来开发不同的页面(成本最高)

2.根据不同端加载不同的CSS样式(可取)

3.根据响应式,来运行不同的样式规则(常用)

4.style预处理器来做

考虑的问题:

1.设置视窗,通过元信息配置 meta

2.掌握媒体查询

3.掌握弹性布局(flex布局)

4.图片响应式

5.视口单位rem/em

问题六:如何修改第三方 npm 包

背景:

来自于设计、产品、老板boss

方案:

1.稳定的库,node_modules,直接改

2.patch方案

‘patch-package’,自动化。

3.fork别人的,直接改源码,改完之后,构建,发布到npm私服。

问题七:使用同一个链接,如何实现PC打开是web应用,手机打开是一个H5应用

背景:

一个链接访问页面,想同时适配PC、Mobile

方案:

1.区分PC、Mobile

--先识别端

js识别,uesrAgent

正则判断

--端内容渲染器(内容加载器)

2.响应式来做

问题八:当QPS达到峰值,该如何处理

背景:

当前端应用的QPS(每秒查询次数)达到峰值时,会对服务器和应用的性能造成很大的压力,甚至可能导致系统崩溃。为了解决这个问题,我们需要采取一系列措施来优化和管理高并发请求。

方案:

1.请求限流

2.请求合并

3.请求缓存

4.任务队列

问题九:如何实现网页加载进度条

拆解:

怎么拿到进度(考虑兼容性、是使用ajax/fetch)

怎么绘制进度:dom、svg

背景:为了提升整站用户加载等待体验,考虑使用加载进度条反馈给给于虎加载过程

方案:

1.页面加载

监听页面加载事件,控制进度条绘制

function simulateLoadingProgress(){
  const progressBar = document.getElementById('progress-bar');
  let width = 0;
  const interval = setInterval(()=>{
    if(width >= 100){
      clearInterval(interval);
      progressBar.style.width = '100%';
      setTimeout(()=>{
        progressBar.style.display = 'none',
      },500);
    }else{
      width += 10;
      progressBar.style.width = width + '%'
    }
  },200);
}

window.addEventListener('load',()=>{
  simulateLoadingProgress();  
})

2.请求实现

function loadResource(url){
  const xhr = new XMLHttpRquest();
  xhr.open('GET'.url,true);
  xhr.onprogress = function(event){
    if(event.lengthComputeable){
      const percentComplete = (event.loaded / even.total)*100;
      document.getElementById('progress-bar').style.width = percentComplete + '%';
    }
  };
  xhr.onload = function(){
    if(xhr.status ===200){
      document.getElementById('progress-bar').style.width = 100%;
      setTimeout(()=>{
        document.getElementById('progress-bar').style.display = 'none';
      },500)
    }
  };
  xhr.send();
}

window.addEventListener('load',()=>{
  loadResource('http://example.com/large-file')  
})

fetch不可以这样子!!

问题十:了解过前端水印功能吗?

背景:

为了保证用户隐私,数据相对安全,实现水印,飞书(名字)waterMar    

文档保护/图片保护/视频保护    

 方案:

明水印:

背景添加水印

内容生成,svg

function createmarkSVG(text){
  const svg = '
    <svg xmlns = "http://www.w3.org/2000/svg" width="200" viewBox="0 0 200 200">
      <text x="50%" y="50%" dy=".35em" text-anchor="middle" fill="rgba(0,0,0,0.1)" font-size="30" transform="rotate(-45,100,100)">
        ${text}
      </text>
    </svg>
  ';
  return 'data:image/svg+xml;base64,${btoa(svg)}';
}

const watermarkText = "Confidential";
document.body.style.backgroundImage = 'url('${createWatermarkSVG(watermarkText)}')';

图片水印 canvas

function addWatermark(imgsrc,watermarkText){
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  const image = new Image();
  image.src = imageSrc;
  image.onload = function(){
    canvas.width = image.width;
    canvas.height = image.height;
    ctx.drawImage(image,0,0);
    ctx.font = '30px Arial';
    ctx.fillstyle = 'rgba(255,255,255,0.5)';
    ctx.fillText(watermarkText,image.width - 150,image.height - 30);
    const watermarkedImage = document.getElementById('watermarkedImage');
    watermarkedImage.src = canvas.toDataUrl('image/png');
  };
}

const imageSrc = document.getElementById('sourceImage').src;
addWatermark(imageSrc,'Confidential');

暗水印:

黑科技,将信息写入到文件二进制代码里去。

问题十一:web应用中如何对静态资源加载失败的场景做降级处理

背景:

图片/css文件/javascript文件/CDN/字体文件/服务端渲染失败

方案:

图片:

1.占位图,alt来描述图片

2.重试机制(404/无权限)

3.上报

<img src="imagejpg" alt="Example Image" onerror="handleImageError(this)">

function handleImageError(image){
  image.onerror = null: //防止死循环
  image.src = 'placeholder.jpg';//使用占位图
}

css文件处理:

资源没加载到:

1.关键样式,通过内联

2.备用样式

3.上报

<link rel="stylesheet" href="style.css" onerror="handleCssError()">

function handleCssError(){
  //加载备用样式
  const fallbackCss = document.createElement('link');
  fallbackCss.rel = 'stylesheet’;
  fallbackCss.href = 'fallback-style.css';
  document.head.appendChild(fallbacks);
}

javascript文件处理:

网络异常,导致资源没加载:

1.内联脚本

2.备用脚本处理

3.上报

CND:

1.本地备份,如果cdn出错了,就使用本地备份

2.动态切换,切换到另一个有用的cdn服务

字体:

1.使用降级字体 apple、微软雅黑

2.webfont处理字体

ssr:

1.降级的html用作渲染

2.切换为客户端渲染

问题十二:怎样设计一个全站请求耗时统计工具

背景:

通过统计工具,可以更清晰地看到整个站点性能情况,首屏加载时间(FP/FCP)

1.监控请求耗时:HTTP、中间件,axios

2.前端监控,监控整个请求,记录耗时数据

3.后端监控:

4.数据汇总:数据清洗加工,数据可视化,可视化图表

方案:

问题十三:请说说你对函数式编程思想的理解

函数式编程的基本概念:

 1.函数为一等公民,函数封装的方式解决问题

2.纯函数,没有任何副作用,相同输入(参数)得到相同输出(返回值)

3.不可变性,

4.高阶函数,函数柯里化

5.函数组合,类似于面向对象继承

总结优点:

1.可测试性,更好写单元测试

2.可维护性

3.并发

4.简洁

问题十四:请说说你对DNS协议的理解:(对应需要复习计算机网络)

将域名映射到IP上

域名解析整个过程:

1.用户输入,解析域名

2.检查自身DNS缓存

3.操作系统DNS缓存

4.本地域名服务器

5.根据本地DNS服务器去查找根DNS服务器、顶级域名服务器(TLD)、权威DNS服务器

6.返回结果,浏览器缓存并向IP发送请求

DNS记录类型:

1.A记录:将域名映射到IPv4地址

2.AAAA记录:将域名映射到IPv6地址

3.CNAME:将域名映射到另外一个域名

4.MX记录:知道邮件服务器

5.TXT:文本信息存储,域名验证,SPF记录

DNS常见问题:

1.DNS解析慢:DNS预解析/使用CDN,CDN节点用户就近/减少外部资源请求,自己域名+oss+cdn

2.DNS劫持:HTTPS,证书保证传输安全性/DNSSEC:DNS安全扩展

3.优化:DNS缓存/nslookup/dig/在线:dns.google.com

问题十五:我们是美团电影的,请问怎么实现一个电影票选座功能

使用canvas来实现选座功能

思路:

1.canvas基础处理

2.座位绘制

3.交互添加

4.座位状态管理,数据结构设计

5.优化,用户体验升级

问题十六:请说说图片性能优化的方案

方案:

1.loading=“lazy”

2.intersection observer检测是否已经到了视窗

3.滚动事件,监听scroll事件,最原始的做法

4.使用库

问题十七:移动端上拉加载,下拉刷新实现方案

背景:

长列表,需要通过上拉加载提升性能。

用户在页面顶部向下拉时,触发页面重新渲染

方案:

上拉加载:

1.滚动事件监听

2.怎么判断触底

3.回调触发列表加载更多

下拉刷新:

1.监听触摸事件,touch、tap

2.显示刷新指示器,显示有没有达到下拉阈值。

3.触发刷新操作

考虑的点:

1.性能优化:节流/防抖

2.用户体验:视觉反馈,下拉刷新的指示器/平滑动画/错误处理

3.兼容:触摸事件/CSS hack

问题十八:深度SEO优化,你都知道哪些细节

SEO优化思路:

1.页面结构优化:语义化标签

2.内容优化:保证页面中关键词的覆盖率

3.技术向SEO优化:站点地图、结构化数据、

问题十八:windows对象上频繁绑定内容,有什么风险

风险分析:

1.命名冲突

2.全局污染

3.安全风险

4.性能问题,增加内存开销

解决方案:

1.模块化

2.命名空间

3.IIFE(形成闭包,形成独立作用域)

4.开启严格模式

5.了解qiankun的快照沙箱实现原理

问题二十:小程序的双线程架构了解吗

双线层:

1.逻辑层(App Service):运行在JavaScriptCore引擎中,负责小程序业务逻辑;数据、时间、网络;不能直接操作视图,需通过通信机制。

2.渲染层(View):运行在WebView中,负责页面渲染;接收逻辑层UI更新指令;独立webview,并行渲染多个页面

双线层的交互:

优化思路:

1.分离业务逻辑和渲染逻辑

2.更新UI通过异步方式

3.并行页面处理,提升切换速度

前端面试中,常常会涉及到对Vue框架的理解和应用场景的提问。一些常见的面试场景包括对mixin、slot、Vue.observable以及key的理解。下面我将逐个回答你提到的问: 1. 对于mixin的理解和应用场景,mixin是一种在Vue组件中复用代码的方式。通过mixin,我们可以将一些通用的逻辑、方法或数据注入到多个组件中,从而实现代码的复用。常见的应用场景包括在多个组件中使用相同的方法或数据,或者在不同的组件中共享一些逻辑。 2. 对于slot的理解和使用场景,slot是Vue中一种实现组件内容分发的机制。通过使用slot,我们可以在父组件中定义一些占位符,并在使用该组件时,通过插入内容填充这些占位符。这样可以实现更灵活的组件复用和自定义组件外观的需求。常见的使用场景包括实现组件的插槽化、动态内容渲染以及实现布局的灵活性。 3. Vue.observable是Vue 2.6新增的全局API,它可以将一个普通的对象转换为响应式对象。通过使用Vue.observable,我们可以在非组件的地方创建响应式的数据。典型的应用场景包括在Vuex之外管理一些全局的状态或数据。 4. 对于Vue中key的原理的理解,key是Vue中用于优化列表渲染的一个特殊属性。通过给每个列表项添加唯一的key属性,Vue可以根据key的变化来判断哪些列表项需要更新、哪些列表项需要新增或删除,从而提高列表渲染的效率。key的原理是通过比较新旧列表项的key来确定它们的关系,并通过最小化变动来更新DOM。 综上所述,前端面试中关于Vue的场景主要包括对mixin、slot、Vue.observable和key的理解与应用场景的回答。这些问涉及了Vue框架中的核心概念和特性,了解它们的使用方法和原理,对于理解Vue的基本原理和能够灵活运用Vue进行开发是非常重要的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值