面试记录

116 阅读4分钟

css 实现自适应的正方形

1、css3 vw 单位
<div className="square"></div>
.square {
    width: 100vw;
    height: 100vw;
}
2、maging、padding 的百分比数值是相对于父元素的宽度计算的
.square {
    width: 100%;
    padding-top: 100%;
    height: 0; // 不设置为 0 的话,内容会撑开高度
}
32 的方案会导致  max-height 失效,要利用伪元素撑开高度
.square {
    overflow: hidden;
    width: 100%;
    &::after {
        content: " ";
        display: block;
        padding-top: 100%;
    }
}

treeshaking

import {xxx} from "xxx";
if (process.env.NODE_ENV === "development") {
	xxx();
}
// xxx 会被 treeshaking 吗?

js 文件、css 文件、图片应该按照什么规则设置浏览器缓存

设置强缓存和协商缓存,强缓存失效就使用协商缓存,资源添加版本号,强制刷新缓存

JSON.stringify 深拷贝有什么缺点

1、Date 类型会变成字符串 2、正则对象会变成空对象 3、对象里的方法、undefined、Symbol 会丢失

JSON.stringify 有几个参数

链接

Object.assign

  • 将所有可枚举属性的值从一个或多个源对象source复制到目标对象,第一个参数是目标对象,其他参数都是源对象,后面对象的属性会覆盖前面对象的属性
  • 如果参数不是对象,会被转换为对象
  • null 和 undefined 作为参数会报错

浅拷贝

  • 如果某个源对象的属性是对象,那么拷贝的是这个属性的引用
  • 多个源对象有同名属性,会被覆盖

用法场景

  • 为对象添加属性或方法
  • 克隆对象,只能克隆对象自身的属性,不克隆原型的属性
  • 合并多个对象

实现对象的深拷贝

代码

判断对象是否有循环引用

代码

实现 Object.create

function Create(o){
    function F(){}
    F.prototype = o;
    return new F();
}

prototype 上的引用类型属性会被实例共享,怎么解决

用正则将手机号中间四位变成星号

str.replace(/(/d{3})\d{4}(/d{4})/, "$1****$2");

react 的性能优化的点有哪些

redux 和 mobx 的区别

多维数组打平有哪些方式

  1. es6 flat 方法
arr.flat(n)// n 表示数组维度,Ifinity表示任意维度
  1. reduce+concat+递归
function flat(arr){
    arr.reduce((pre,next) => {
        return pre.concat(Array.isArray(next) ? flat(next) : next)
    },[])
}

react同时设置多个setState,怎么做只让组件重新渲染一次

  1. react对多次状态更新会批量处理,同步代码中的setState会批量更新,异步代码(setTimeout、promise.then)的setState会触发多次更新;
  2. 可以使用useRef,不会触发多次更新;
  3. 将多个state变量合并到一个中;

判断空对象的方法有哪些

  1. object.entries()或Object.keys(),返回空数组
  2. JSON.stringify()转为"{}"
  3. for...in+额外变量,变量初始值设为true,若不为空对象,在循环里设置为false

实现深拷贝需要考虑哪些问题

  1. 需要考虑的点
  • 日期格式
  • 正则对象
  • 循环对象引用
  • 不能丢失原对象的原型
  1. 简易版
// 判断是否是对象
    const isRefferenceObj = (value)=> typeof value === 'object' && typeof value !== null;
    const deepCopy = (obj) => {
        if (!isRefferenceObj(obj)) {
          return obj;
        }
        let newObj = Array.isArray(obj)?[]:{};
        Object.keys(obj)?.forEach(key => {
          const value = obj[key];
          newObj[key] = isRefferenceObj(value)?deepCopy(value):value;
        })
        return newObj;
    }
  1. 完整版
  const deepCopy = (obj,map=new WeakMap()) => {
    if (obj.constructor === Date) {
      return new Date(obj);
    }
    if (obj.constructor === RegExp){
      return new RegExp(obj);
    }
    if (typeof obj !== 'object'||obj === null) {
      return obj;
    }
    const prototype = Object.getPrototypeOf(obj);
    const newObj = Object.create({},prototype)
    // 通过map对象来防止循环引用
    map.set(obj,true);
    Reflect.ownKeys(obj)?.forEach(key => {
      const value = obj[key];
      if(typeof value !=='object'||typeof value===null){
        newObj[key] = value;
      } else {
        if (map.has(value)) {
          newObj[key] = map.get(value)
        } else {
          newObj[key] = deepCopy(value);
        }
      }
    })
    return newObj;
  }

for 循环和 forEach里调用await,会有什么不同

  1. for会按照顺序输出,forEach会一次性输出并且不保证顺序
  2. 因为forEach内部就是一个函数,按循环执行,并没有异步的相关处理逻辑

详解

怎么显示比12px更小的字体

  1. zoom
<style type="text/css">
    .span1{
        font-size: 12px;
        display: inline-block;
        zoom: 0.8;
    }
    .span2{
        display: inline-block;
        font-size: 12px;
    }
</style>
<body>
    <span class="span1">测试10px</span>
    <span class="span2">测试12px</span>
</body>
  1. tramsform:scale()
<style type="text/css">
    .span1{
        font-size: 12px;
        // scale只对能设置宽高的元素起作用,所以需要设置inline-block
        display: inline-block;
        -webkit-transform:scale(0.8);
    }
    .span2{
        display: inline-block;
        font-size: 12px;
    }
</style>
<body>
    <span class="span1">测试10px</span>
    <span class="span2">测试12px</span>
</body>

对象数组去重

  1. filter+map
function uniqueArr(arr){
    let map = new Map();

    return arr.filter(item => {
        if (!map.has(item.id)) {
            map.set(item.id,true);
            return true;
        } else {
            return false
        }
        
    })
    // return arr.filter(item => !map.has(item.id)&&map.set(item.id,true))
}

0.2+0.3精度问题、大数据精度问题

  1. js 最多能精确到小数点后16位,所以可以按照小于这个位数做个精确度截取
function strip(num, precision = 12) {
  return +parseFloat(num.toPrecision(precision));
}
  1. 将小数转成整数计算
/**
 * 精确加法
 */
function add(num1, num2) {
  const num1Digits = (num1.toString().split('.')[1] || '').length;
  const num2Digits = (num2.toString().split('.')[1] || '').length;
  const baseNum = Math.pow(10, Math.max(num1Digits, num2Digits));
  return (num1 * baseNum + num2 * baseNum) / baseNum;
}
  1. 使用Math.js或BigDecimal.js

重复请求有哪些处理方法

css 不同大小的字体底部对齐

  • 父元素设置display:flex;子元素设置align-items:baseline

react 编写的页面怎么优化渲染性能

react 的useCallback在什么场景使用

fiber中断后如何知道从哪儿开始

react组件的初始渲染流程和更新渲染流程

不使用import,怎么正常渲染组件

react.lazy的原理

iframe 如何通信

页面的按钮如何做权限控制