前端手写面试题收集

2 阅读4分钟

weakMap和Map的区别

weakMap弱引用,不影响垃圾回收器的工作

大数据量渲染优化,后端一次性返回10万条数据

  • vxe-table
  • 多行数据长任务计算使用Web.worker
  • setTimeOut分页渲染
  • 也可以 使用requestAmimationTrame代替setTimeOut
  • 文档碎片+requestAmimationTrame

前端数据埋点

  • 手动埋点

  • 可视化埋点

  • 无痕埋点:也叫自动埋点、全埋点。即对全局所有事件和页面加载周期进行拦截埋点

  • 页面埋点:统计用户进入或者离开页面的信息(页面浏览次数-pv、浏览页面人数-uv、页面停留时长、设备信息)

  • 点击埋点:统计用户在页面浏览中触发的点击事件。如按钮、导航或者图片的点击次数

  • 曝光埋点:统计具体元素是否得到有效曝光

  • 约定规范,通过统一接口来处理埋点逻辑

手写题(现场常考)

1. 金额格式化(保留两位小数)

js

function formatMoney(val) {
  val = val.toString().replace(/[^0-9.]/g, '')
  if (val.split('.').length > 2) val = val.slice(0, -1)
  return Number(val || 0).toFixed(2)
}

2. 手机号脱敏

js

function maskPhone(phone) {
  return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}

3. 防抖(搜索 / 输入用)

js

function debounce(fn, delay) {
  let timer
  return (...args) => {
    clearTimeout(timer)
    timer = setTimeout(() => fn(...args), delay)
  }
}

JS 基础 & 手写题答案

1. 防抖(高频手写)

js

function debounce(fn, delay) {
  let timer = null
  return function (...args) {
    clearTimeout(timer)
    timer = setTimeout(() => fn.apply(this, args), delay)
  }
}

2. 节流

js

function throttle(fn, delay) {
  let flag = true
  return function (...args) {
    if (!flag) return
    flag = false
    setTimeout(() => {
      fn.apply(this, args)
      flag = true
    }, delay)
  }
}

3. 手机号脱敏

js

function maskPhone(phone) {
  return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}

4. 金额格式化

js

function formatMoney(num) {
  return Number(num).toFixed(2)
}

5. 深拷贝简单版

js

function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') return obj
  const res = Array.isArray(obj) ? [] : {}
  for (let k in obj) {
    res[k] = deepClone(obj[k])
  }
  return res
}

如何判断一个对象是空对象

使用 JSON 自带的.stringify 方法来判断: image.png 使用 ES6 新增的方法 Object.keys()来判断: image.png

编写一个数组去重的方法

function sort(arr){
    for(var i=0; i < arr.length; i++) {
       for (var j = i+1; j < arr.length; j++) {
          if (arr[i] == arr[j]) {
            arr.splice(j,1)
               j--  // 删除一个元素后,后面的元素会依次往前,下标也需要依次往前
           }
         }
       }
       return arr
}

冒泡算法排序

for (var i=0; i < arr.length-1;i++) {
    for (var j=0;j < arr.length-1-i; j++) {
        if (arr[j]>arr[j+1]) {
            var temp = arr[j]
            arr[j] = arr[j+1]
            arr[j+1] = temp
        }
    }
}

元素水平垂直居中的方法有哪些?如果元素不定宽高呢?

  • 利用定位+margin:auto
<style>
    .father{
        width:500px;
        height:300px;
        border:1px solid #0a3b98;
        position: relative;
    }
    .son{
        width:100px;
        height:40px;
        background: #f0a238;
        position: absolute;
        top:0;
        left:0;
        right:0;
        bottom:0;
        margin:auto;
    }
</style>
<div class="father">
    <div class="son"></div>
</div>
  • 利用定位+margin:负值
<style>
    .father {
        position: relative;
        width: 200px;
        height: 200px;
        background: skyblue;
    }
    .son {
        position: absolute;
        top: 50%;
        left: 50%;
        margin-left:-50px;
        margin-top:-50px;
        width: 100px;
        height: 100px;
        background: red;
    }
</style>
<div class="father">
    <div class="son"></div>
</div>
  • 利用定位+transform
<style>
    .father {
        position: relative;
        width: 200px;
        height: 200px;
        background: skyblue;
    }
    .son {
        position: absolute;
        top: 50%;
        left: 50%;
       transform: translate(-50%,-50%);
        width: 100px;
        height: 100px;
        background: red;
    }
</style>
<div class="father">
    <div class="son"></div>
</div>
  • table布局

设置父元素为display:table-cell,子元素设置 display: inline-block。利用vertical和text-align可以让所有的行内块级元素水平垂直居中

<style>
    .father {
        display: table-cell;
        width: 200px;
        height: 200px;
        background: skyblue;
        vertical-align: middle;
        text-align: center;
    }
    .son {
        display: inline-block;
        width: 100px;
        height: 100px;
        background: red;
    }
</style>
<div class="father">
    <div class="son"></div>
</div>

flex布局

<style>
    .father {
        display: flex;
        justify-content: center;
        align-items: center;
        width: 200px;
        height: 200px;
        background: skyblue;
    }
    .son {
        width: 100px;
        height: 100px;
        background: red;
    }
</style>
<div class="father">
    <div class="son"></div>
</div>

grid布局

<style>
    .father {
            display: grid;
            align-items:center;
            justify-content: center;
            width: 200px;
            height: 200px;
            background: skyblue;
 
        }
        .son {
            width: 10px;
            height: 10px;
            border: 1px solid red
        }
</style>
<div class="father">
    <div class="son"></div>
</div>    

实现一个trim方法

  1. 通过原型创建字符串的trim()
//去除字符串两边的空白
 
String.prototype.trim=function(){
  return this.replace(/(^\s*)|(\s*$)/g, "");
}
 
//只去除字符串左边空白
 String.prototype.ltrim=function(){
  return this.replace(/(^\s*)/g,"");
}
 
//只去除字符串右边空白
String.prototype.rtrim=function(){
  return this.replace(/(\s*$)/g,"");
 
}

2. 通过函数实现

function trim(str){
  return str.replace(/(^\s*)|(\s*$)/g, "");
}

实现一个三角形(CSS绘制三角形主要用到的是border属性,也就是边框)

div {
    width: 0;
    height: 0;
    border-top: 100px solid red;
    border-right: 100px solid transparent;
}

画一条0.5px的线

采用transform: scale()的方式,该方法用来定义元素的2D 缩放转换(transform: scale(0.5,0.5);)

js手写基础深拷贝函数(处理对象 / 数组)

function deepClone1(target) { 
// 1. 如果不是对象/数组,直接返回原值(基本数据类型) 
    if (typeof target !== 'object' || target === null) { 
      return target;
    } 
// 2. 判断是数组还是对象,初始化结果 
    const result = Array.isArray(target) ? [] : {};

// 3. 递归遍历所有属性 
  for (const key in target) { // 只拷贝自身属性,排除原型链属性 
   if (target.hasOwnProperty(key)) { 
     result[key] = deepClone(target[key]); 
    } 
   } 
   
   return result; 
 }
 
 function deepClone2(obj) { 
    // 基本类型直接返回 
    if (typeof obj !== 'object' || obj === null) { 
      return obj; 
    } 
    
    // 数组 or 对象 
    let clone = Array.isArray(obj) ? [] : {}; 
    
    // 递归拷贝 
    for (let key in obj) { 
      if (obj.hasOwnProperty(key)) { 
        clone[key] = deepClone(obj[key]); 
      } 
     } 
    
    return clone; 
 }