前端面试题 一

61 阅读9分钟

1.react虚拟dom是怎么回事

  1. 虚拟DOM本质上就是一个对象,和真实DOM相比,它少了默认挂载的很多属性和方法,在开发过程我们并不需要去关心这些属性和方法,所以从结构上来看,虚拟DOM比真实DOM轻很多。
  2. 从操作角度看,原生DOM要想性能高会带来复杂度,不利于项目开发
  3. 而虚拟DOM将所有的操作聚集到一块,计算出所有的变化后,统一更新一次虚拟DOM

优势:

  • 提高效率: 使用原生js的时候,我们需要的关注点在操作DOM上,而React会通过虚拟DOM来确保DOM的匹配,我们不需要关注如何操作、怎样更新DOM, 我们更关注业务逻辑,从而提高开发效率
  • 性能提升:
    • React会将整个DOM保存为虚拟DOM,如果有更新,都会维护两个虚拟DOM,以此来比较之前的状态和当前的状态,并会确定哪些状态被修改,然后将这些变化更新到实际DOM上,一旦真正的DOM发生改变,也会更新UI

    • 浏览器在处理DOM的时候会很慢,处理Javascript会很快

    • 所以在虚拟DOM感受到变化的时候只会更新局部,而非整体。同时,虚拟DOM会减少了非常多的DOM操作,所以性能会提升很多

    • 它的优势在于diff算法和批量处理策略,将所有的DOM操作搜集起来,一次性去改变真实的DOM,但在首次渲染上,虚拟DOM会多了一层计算,消耗一些性能,所以有可能会比html渲染要慢。

    • 虚拟DOM实际上是给我们找了一条最短最近的路径,并不是说比DOM操作的更快,而是路径最简单

  • 超强的兼容性:
    • 浏览器的兼容和跨平台兼容
    • react基于虚拟DOM实现了一套自己的事件机制,并且模拟了事件冒泡和捕获过程,采取事件代理、批量更新等方法,从而磨平了各个浏览器的事件兼容问题
    • 对于跨平台,react和react native都是根据虚拟DOM画出相应平台的UI层,只不过不同的平台画法不同而已

2.js如何创建一个对象

  • 字面量
  • Object.create()

3.如何清除浮动

  1. 利用clear样式
  2. 父元素结束标签之前插入清除浮动的块级元素
  3. 利用伪元素(clearfix) :after{ content: ''; display: block; clear: both; }
  4. 利用overflow清除浮动

BFC(块级格式化上下文):

  1. overflow: hidden,auto,scroll
  2. display: inline-block, inline-table, inline-flex, inline-grid, flex, table-caption, inltable-cell, table, grid
  3. position: fixed, absolute

两栏布局:

往往是一个定宽栏和一个自适应栏并排展示

  1. flex. 父组件display: flex. 左侧子元素固定宽度200px, 右侧子元素flex:1
  2. 父元素添加BFC(防止下方元素飞到上方展示), 左边栏float左浮, 右侧marginLeft左侧宽度(撑出内容块做内容展示)

三栏布局:

  1. 浮动。左右float, 中间mārgin:0.
  2. 绝对定位,左右position: absolute
  3. display: table \ display:table-cell
  4. display: flex
  5. display: grid \ grid-template-columns: 300px auto 300px

flex有三个属性,分别是?

  • grow:父容器宽度大于子元素宽度时对元素做出调整
  • shrink:压缩
  • basis:width

4.如何想让一个元素在页面看不见

  1. display: none 元素在页面上彻底消失,元素本身占有的空间会被其他元素占有,会导致浏览器的重排和重绘,无法响应点击事件
  2. visibility: hidden 仅仅是隐藏元素,DOM节点会存在,只是在不可见状态,不会触发重排,但会重绘,无法响应点击事件
  3. opacity: 0 改变元素透明度,元素不可见,占据页面空间,可以响应事件
  4. 设置height、width模型属性为0 元素不可见,不占据页面空间,无法响应点击事件,如果有子元素,应该设置其overflow: hidden来隐藏
  5. position: absolute 将元素移出可视区域,元素不可见,不影响页面布局
  6. clip-path 裁剪,元素不可见,不占据页面空间,无法响应点击事件

5.react-router的原理

路由的本质就是页面的url发生改变时,页面的显示结果可以根据url的变化而变化,但是页面不会刷新。 因此,可以通过前端路由实现单页(SPA)应用,react-router主要分成了几个不同的包:

  • react-router: 实现了路由的核心功能
  • react-router-dom: 基于react-router, 加入了在浏览器运行环境下的一些功能
  • react-router-native: 基于react-router, 加入了react-native运行环境下的一些功能
  • react-router-config: 用于配置静态路由的工具库

6.盒模型

对文档进行布局的时候,浏览器的渲染引擎会根据标准之一的css寄出框盒模型,将所有元素表示为一个个矩形的盒子。

在css中,盒子模型可以分成:

  • W3C标准盒模型 : 总宽度 = width + padding + border + margin;
  • IE怪异盒模型 : 总宽度 = width + margin (width包含了padding和border的值)

7.页面中的性能优化

  • 图片: 压缩,格式webp,懒加载,小图转为base64减少请求次数
  • css: 减少重排和重绘, 样式选择器的层级不要太深
  • js: 文件压缩,文件分片,对资源进行缓存
  • react: memo高阶组件减少不必要的渲染,不需要渲染的数据不要放到state里

8.什么是跨域?如何解决跨域的,jsonp有什么缺点

  • 浏览器同源策略限制:协议、域名、端口号中任意一个不同
  • 解决方法:
    • jsonp
      • 原理: script标签的src不受同源策略的限制
      • 后端返回一段js代码,代码的内容是一个前端定义好的函数的调用,把需要返回的内容传递进去
      • 只能发送get请求,不安全,不好维护
      • 兼容性比较好
    • 打包工具自带的服务器代理请求,解决跨域
      • 原理:跨域是浏览器特有的,而服务器和服务器之间不存在跨域。
    • 后端解决
      • 只要后端在响应头中加上对应的字段,浏览器就不会再报错。
    • nginx服务器代理解决跨域
    (参考: juejin.cn/post/735207…

9.如果你接到一个项目如何从头开始的(需求,技术选型,技术环境,依赖哪些组件)

10.js的继承(口述代码)

js中的继承主要基于原型链(Prototype chain)

  1. 原型链继承:通过将子类的原型对象指向父类的实例,实现属性和方法的继承
  2. 借用构造函数继承:在子类构造函数中调用父类构造函数,通过call或apply绑定this
  3. 结合原型链继承和构造函数继承
  4. 原型式继承:基于已有对象创建新对象,通过Object.create()实现
  5. 寄生组合继承:通过借用构造函数继承属性,通过原型链混成形式继承方法「最优」
  6. class继承:extends+super(),语法糖,底层基于寄生组合式继承

(参考:juejin.cn/post/747550…

11.闭包(闭包有什么缺点)

闭包让你可以在一个内层函数中访问到其外层函数的作用域。在js中,每当创建一个函数,闭包就会在函数创建的同时被创建出来,作为函数内部与外部连接起来的一座桥梁。

闭包的使用场景:

  • 创建私有变量
  • 延长变量的生命周期

柯里化函数: 柯里化的目的在于避免频繁调用具有相同参数函数的同时,又能够轻松的重用

缺点:内存泄露。

当它引用了大量数据或长时间维持对外部作用域变量的引用,阻止了垃圾回收机制回收不再使用的内存空间。因为每次清理函数的执行上下文时,有被内部函数调用的变量,导致还留有一些变量在内存中,这就是闭包,当数据量太大的时候,闭包较多,而调用栈的容量有限,大量的闭包导致栈满或使得调用栈的可用内存变小了,这就是内存泄漏。

解决内存泄露的方法:

  • 手动释放闭包的引用:在闭包不再需要访问外部变量时,显式地将闭包或者外部变量设置为null。这样可以断开闭包对外部作用域变量的引用,使得垃圾回收机制能够回收这些变量占用的内存。
  • 事件处理和定时器清理:确保为所有的事件监听器和定时器设置清除机制,避免它们长时间持有闭包和相关的外部变量。

12.js的作用域有哪些 安全隐患

  • 全局作用域:任何不在函数中或是大括号中声明的变量,都是在全局作用域下,全局作用域下声明的变量可以在程序的任意位置访问
  • 函数作用域:也叫局部作用域,如果一个变量在函数内部声明的,它就在一个函数作用域下面。这些变量只能在函数内部访问,不能在函数以外去访问
  • 块级作用域:ES6中引入了let和const关键字,在大括号中使用let和const声明的变量存在于块级作用域中。在大括号之外不能访问这些变量

作用域链:

  • 当在javascript中使用一个变量的时候,首先javascript引擎会尝试在当前作用域下去寻找改变量,如果没找到,再到它的上层作用域寻找,以此类推直到找到改变量或是已经到了全局作用域
  • 如果在全局作用域里仍然找不到该变量,它就会在全局范围内隐式声明该变量(非严格模式下)或是直接报错
  • 把作用域比喻成一个建筑,这份建筑代表程序中的嵌套作用域链,第一层代表当前的执行作用域,顶层代表全局作用域
  • 变量的引用会顺着当前楼层进行查找,如果找不到,则会往上一层找,一旦到达顶层,查找的过程都会停止