2020前端面试题汇总

2,820 阅读9分钟

持续更新中...

记录一下面试被问到的技术问题,顺便回顾一下知识点。
由于是按面试顺序汇总,问题之间无相关性,就不做目录了,直接翻阅右下角的系统目录吧

>> 02.25 12:00 --------------------------------------------

vue和react中父子传值的方式

  • vue:父向子传值props、子向父传值$emit
  • react:props

react中父获取子组件中的方法

  • 使用refs,他是使用 React.createRef() 创建的,并通过 ref 属性附加到 React 元素,再通过current来访问节点(或者使用回调的形式)
this.XXX = React.createRef()
this.XXX.current //节点
<Demo ref={this.XXX}></Demo>

//回调形式
<Demo ref={element => this.XXX = element}></Demo>
  • 当 ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的 ref 接收底层 DOM 元素作为其 current 属性。
  • 当 ref 属性用于自定义 class 组件时,ref 对象接收组件的挂载实例作为其 current 属性,这时就可以调用子组件的方法和属性,也是一种传值方式。
  • 你不能在函数组件上使用 ref 属性,因为他们没有实例,但是可以再函数组件内部使用,只要它指向一个 DOM 元素或 class 组件。
  • 【扩展】refs转发,使函数组件也能获取到ref
    • 第二个参数 ref 只在使用 React.forwardRef 定义组件时存在
    • 这种转发还经常用在高阶组件中,将ref传递到高阶组件返回的组件中
const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// 你可以直接获取 DOM button 的 ref:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;

key的作用

  • 每个key对应一个组件,相同的key react认为是同一个组件,这样后续增加或删除或改变顺序时,相同的key对应组件都不会被重新创建,提升了性能

前端加密

  • 参考
  • 利用插件 js-md5
  • base64加密 利用 window.btoa("XXX"); 编码;window.atob();解码

vue和react的区别

  • 参考
  • react整体是函数式的思想,把组件设计成纯组件,状态和逻辑通过参数传入,所以在react中,是单向数据流;vue则是响应式的,也就是基于是数据可变的,通过对每一个属性建立Watcher来监听,当属性变化的时候,响应式的更新对应的虚拟dom。
  • react的思路是all in js,vue则是单文件组件,可以把html、css、js写到一个文件中,html提供了模板引擎来处理

浏览器存储方式及其不同

  • 存储大小限制也不同,cookie数据不能超过4K,sessionStorage和localStorage可以达到5M
  • sessionStorage:仅在当前浏览器窗口关闭之前有效;localStorage:始终有效,窗口或浏览器关闭也一直保存,本地存储,因此用作持久数据;cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭
  • sessionStorage:不在不同的浏览器窗口中共享,即使是同一个页面;localstorage:在所有同源窗口中都是共享的;也就是说只要浏览器不关闭,数据仍然存在;cookie: 也是在所有同源窗口中都是共享的.也就是说只要浏览器不关闭,数据仍然存在

301 302 状态码是什么

  • 状态码一般由3位构成: 1xx : 表示请求已经接受了,继续处理。 2xx : 表示请求已经处理掉了。 3xx : 重定向。 4xx : 一般表示客户端有错误,请求无法实现。 5xx : 一般为服务器端的错误。
  • 常见的状态码
    • 200 OK 客户端请求成功
    • 301 Moved Permanently 请求永久重定向
    • 302 Moved Temporarily 请求临时重定向
    • 304 Not Modified 文件未修改,可以直接使用缓存的文件
    • 403 Forbidden 服务器收到请求,但是拒绝提供服务。服务器通常会在响应正文中给出不提供服务的原因。
    • 404 Not Found 请求的资源不存在,比如输入了错误的URL
    • 500 Internal Server Error 服务器发生不可预期的错误,导致无法完成客户端的请求

componentWillRecieveProps 不再推荐?

  • 以下生命周期钩子将在React17之后的版本中删除:componentWillMount、componentWillUpdate、componentWillRecieveProps,取而代之的是在16.3版本中带有UNSAFE_前缀的这三个钩子
  • 新的生命周期
    • 挂载阶段:constructor() => render() => 更新DOM和refs => componentDidMount()
    • 更新阶段:新的props、setState()、forceUpdate() => render() => 更新DOM和refs => componentDidUpdate()
    • 卸载阶段:componentWillUnmount()

for 和 forEach 区别 哪个性能更优

  • 个人认为 从日常业务开发中来说 for 性能更优 因为for可以使用 break 或者 continue 在适当的时机跳出 而 forEach 是没有办法的 看网上有人进行来性能测试 貌似同样的循环次数 也是for更优

vuex和redux区别

  • 参考
  • 改进了Redux中的Action和Reducer函数,以mutations变化函数取代Reducer, 无需switch,只需在对应的mutation函数里改变state值即可
  • 由于Vue自动重新渲染的特性,无需订阅重新渲染函数,只要生成新的State即可
  • Vuex数据流的顺序是:View调用store.commit提交对应的请求到Store中对应的mutation函数->store改变(vue检测到数据变化自动渲染)

箭头函数和普通函数区别

  • 箭头函数是匿名函数,不能作为构造函数,不能使用new
  • 箭头函数不绑定arguments,取而代之用rest参数...解决
  • 箭头函数不绑定this,会捕获其所在的上下文的this值,作为自己的this值

Promise all 和 race 区别

  • Promise.all() 处理多个异步Promise,全部成功才会进入then()
  • Promise.race() 处理多个异步Promise,有一个成功来就会进入then()

setState 第二个参数用法

  • 用于处理state更新成功之后的操作

react 更新 props的生命周期

  • 更新阶段:新的props、setState()、forceUpdate() => render() => 更新DOM和refs => componentDidUpdate()

react router Link 和 a 有什么区别

  • Link组件不会刷新页面,只会对变化的DOM进行渲染,a 会刷新页面 有一个视觉上的页面闪烁,会全部重新渲染 这很大程度的提高了性能

冒泡排序

  • 它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
function bubbleSort(arr) {
    var i = arr.length, j;
    var tempExchangVal;
    while (i > 0) {
        for (j = 0; j < i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                tempExchangVal = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tempExchangVal;
            }
        }
        i--;
    }
    return arr;
}
 
var arr = [3, 2, 4, 9, 1, 5, 7, 6, 8];
var arrSorted = bubbleSort(arr);
console.log(arrSorted);
alert(arrSorted);

深度优先和广度优先

  • 参考
  • 深度优先遍历就是一种不撞南墙不会头的算法,他会把一条路走完之后再回溯到有分叉的节点继续遍历
  • 在广度优先搜索时,会从起点开始“一层一层”扩展的方法来遍历,扩展时每发现一个点就将这个点加入到队列,直到整张图都被遍历过位置。

css垂直居中的方法

  • 参考
  • 常用
    • flex
    • transform
    • line-height

>> 02.21 15:04 --------------------------------------------

vue中computed和watch的区别

  • computed 计算属性,对绑定到实例上的数据进行处理
    • 基于它们的响应式依赖进行 缓存,只在相关响应式依赖发生改变时它们才会重新求值
    • 无法处理异步操作
    • 默认只要getter,也可以设置setter,接受设置的值为参数,当要设置计算属性时会调用setter
  • watch 监听属性,当需要在数据变化时执行异步或开销较大的操作时使用
    • 无缓存,只要监听的属性变化就会触发
    • 可进行异步处理
    • 接受两个参数,第一个是最新值,第二个是以前的值
    • 还支持 deep 和 immediate 两个选项,deep 可发现对象内部值的变化;immediate 会立即执行一次
// 观察的属性名
    person:{
      handler(value){
        alert("我的name是:"+value.name)
        alert("我的age是:"+value.age)
      },
      deep:true
    }

vue生命周期

  • beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed
  • ajax 请求一般在created中

vue更新机制原理

  • 通过Object.defineProperty把data中的各数据属性改为访问器属性,来劫持每个属性的setter、getter;setter劫持到数据变化后,作为发布者 发布通知,订阅者们接到通知后更新数据。

vue双向绑定原理

  • 采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。
<!--一个简单的用js实现双向绑定的例子-->
<html>
    <body>
        <div id="app">
            <input type="text" id="txt"/>
            <p id="show"></p>
        </div>
    </body>
    <script type="text/javascript">
        var obj = {}
        Object.defineProperty(obj, 'txt', {
            get: function(){
                return obj
            },
            set: function(newVal){
                document.getElementById('txt').value = newVal
                document.getElementById('show').innerHTML = newVal
            }
        })
        document.addEventListener('keyup', function(e){
            obj.txt = e.target.value
        })
    </script>
</html>

vue父子组件传值有哪些方式

  1. 父向子传值:props
  2. 父向子传值:$parent(获取了父的实例)
  3. 子向父传值:$emit
  4. 子向父传值:$refs(获取了子的实例)
  5. 祖先向每个后代传值: provide/inject
provide: function () {
  return {
    getMap: this.getMap
  }
}
inject: ['getMap']
  1. vuex

vuex的属性有哪些,如何改变state

  • state、getters、mutaions、actions
  • 可以在mutaions定义方法去更改state 或者 在actions中定义异步方法去执行mutations中的更改state的方法

this的指向有哪些

  • 参考
  • 谁最终调用函数,this指向谁,this指向的,永远只可能是对象
  • 通过函数名()直接调用:this指向window
  • 通过对象.函数名()调用的:this指向这个对象
  • 函数作为数组的一个元素,通过数组下标调用的:this指向这个数组
  • 函数作为window内置函数的回调函数调用:this指向window( setInterval setTimeout 等)
  • 函数作为构造函数,用new关键字调用时:this指向新new出的对象
  • 严格模式中的默认的this不再是window,而是undefined

ES6会常用到哪些特性

  • 模版字符串、扩展运算符、数组中新增的各种方法、箭头函数、let、Promise、Module、Class

继承方式

  • 原型链继承,一个类型A的原型对象是另一个类型B的实例,那么A就继承了B中原型对象的方法
  • ES6的语法糖 Class extends
  • 拷贝继承?

什么是闭包

RN热更新

  • react-native-update pushy账号

是否有接触过自动化部署

webpack了解多少

>> 02.19 18:06 --------------------------------------------

原生发一个ajax请求

  1. 创建异步对象 var xhr = new XMLHttpRequest();
  2. 设置请求行 open(请求方式,请求url) xhr.open("get","validate.php?username="+name)
  3. 设置请求(GET方式忽略此步骤)头:setRequestHeader() xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
  4. 设置请求体 send()xhr.send(null) 或 xhr.send("username="+name);
  5. 让异步对象接收服务器的响应数据
xhr.onreadystatechange = function(){ 
    if(xhr.status == 200 && xhr.readyState == 4){ 
        console.log(xhr.responseText);
    }
}
  • readyState
    • 0: 请求未初始化
    • 1: 服务器连接已建立
    • 2: 请求已接收
    • 3: 请求处理中
    • 4: 请求已完成,且响应已就绪

浏览器敲回车到渲染整个页面的过程

  1. 读取缓存:搜索自身的 DNS 缓存。(如果 DNS 缓存中找到IP 地址就跳过了接下来查找 IP 地址步骤,直接访问该 IP 地址。)
  2. DNS 解析:将域名解析成 IP 地址
  3. TCP 连接:TCP 三次握手,简易描述三次握手
    • 客户端:服务端你在么?
    • 服务端:客户端我在,你要连接我么?
    • 客户端:是的服务端,我要连接。
    • 连接打通,可以开始请求了
  4. 发送 HTTP 请求
  5. 服务器处理请求并返回 HTTP 报文
  6. 浏览器解析渲染页面
  7. 断开连接:TCP 四次挥手

http和https的区别

  • HTTPS协议可以理解为HTTP协议的升级,就是在HTTP的基础上增加了 数据加密。在数据进行传输之前,对数据进行加密,然后再发送到服务器。这样,就算数据被第三者所截获,但是由于数据是加密的,所以你的个人信息让然是安全的。这就是HTTP和HTTPS的最大区别。

闭包的应用场景

  • 参考
  • 原生的setTimeout传递的第一个函数不能带参数,通过闭包可以实现传参效果
  • 函数防抖
  • 封装私有变量

react 的事件和原生事件区别

  • 参考
  • React合成事件一套机制:React并不是将click事件直接绑定在dom上面,而是采用事件冒泡的形式冒泡到document上面,然后React将事件封装给正式的函数处理运行和处理。

>> 02.19 17:06 --------------------------------------------

箭头函数和普通函数的区别

  • 箭头函数是匿名函数,不能作为构造函数,不能使用new
  • 箭头函数不绑定arguments,取而代之用rest参数...解决
  • 箭头函数不绑定this,会捕获其所在的上下文的this值,作为自己的this值

let和var的区别,什么时变量提升

  • let、const不存在变量提升、不允许重复声明、块级作用域
  • 变量提升:变量可以在声明之前使用,值为undefined

for in 和 for of 的区别 怎么避免原型链属性被遍历?

  • for in 取 key; for of 取 value
  • for of 无法遍历对象
  • 一个数据结构只要部署了 Symbol.iterator 属性, 就被视为具有 iterator接口, 就可以使用 for of循环

Promise的用法

  • new Promise((resolve, reject) => ...).then().catch()

setState时发生了什么

  • 参考
  • 可以接受一个对象或者一个函数(接受参数为前一个state和props),第二个参数是一个回调函数用于处理状态更新后的操作
  • setState()方法通过一个队列机制实现state更新,当执行setState()的时候,会将需要更新的state合并之后放入状态队列,而不会立即更新this.state(可以和浏览器的事件队列类比)。如果我们不使用setState而是使用this.state.key来修改,将不会触发组件的re-render。

react hook的设计原由

  • 参考
  • 在组件之间复用状态逻辑很难
  • 相互关联且需要对照修改的代码被进行了拆分,而完全不相关的代码却在同一个方法中组合在一起。如此很容易产生 bug,并且导致逻辑不一致。

react如何阻止状态更新

  • 利用shouldComponentUpdate

react中key的作用 有相同key时怎么处理

  • 有了key属性后,就可以与组件建立了一种对应关系,每个key 对应一个组件,相同的key react认为是同一个组件,这样后续相同的key对应组件都不会被创建
  • 如果你选择不指定显式的 key 值,那么 React 将默认使用索引用作为列表项目的 key 值

react父子组件之间传递数据的方式

  • props
  • context
  • redux

ts中函数默认值和可选参数

  • function buildName(firstName = "XXX", lastName?: string) {}

描述一下设计点赞组件的思路

>> 02.19 15:37 --------------------------------------------

let与var区别

  • let、const不存在变量提升、不允许重复声明、块级作用域

浏览器存储

  • sessionStorage:仅在当前浏览器窗口关闭之前有效;localStorage:始终有效,窗口或浏览器关闭也一直保存,本地存储,因此用作持久数据;cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭

React生命周期

项目迁移怎么考虑

  • 参考
  • 理清项目结构、页面结构、使用技术栈,规范代码。

组件式开发的见解

React Hook 版本

  • @16.8

函数组件和Class组件的区别

  • 函数组件没有状态、生命周期、this

pushy热更新

  • react-native-update

除了redux还了解过其他状态管理库吗?

  • React 自带的 Context
  • 参考

地图定点数据有很多时怎么处理?

antDesign 和 Bootstrap 的区别

  • antDesign 组件库
  • Bootstrap 样式库

>> 02.05 17:00 --------------------------------------------

this.$nextTick

  • 参考
  • 将回调延迟到下次 DOM 更新循环之后执行。状态改变后页面不会立即改变,而是等到下一次更新才会改变。
  • 在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中
  • 在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中。
  • 内部实现,先判断是否原生支持promise,如果支持,则利用promise来触发执行回调函数;否则,如果支持MutationObserver,则实例化一个观察者对象,观察文本节点发生变化时,触发执行所有回调函数;如果都不支持,则利用setTimeout设置延时为0。

<keep-alive>

  • 参考
  • 当组件在 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行
  • 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在组件的父组件链中
  • include - 字符串或正则表达式。只有名称匹配的组件会被缓存
  • exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存

Promise.all()

  • 只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数
  • 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
  • 如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法。

Vue 生命周期

  • beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed
  • ajax 请求一般在created中

sass Mixin 混合指令

  • 定义可重复使用的样式,避免了使用无语意的 class
  • @mixin 定义混合;@include 引用混合

原型链和闭包

let、const、var 区别

  • 参考
  • let、const不存在变量提升、不允许重复声明、块级作用域

>> 02.06 14:00 --------------------------------------------

对象和数组的拼接

  • 对象的拼接
    • Object.assign(target, source) 将对象source合并到对象target中,target会被改变
    • {...a, ...b}
  • 数组的拼接
    • Array.concat() 不会改变原数组
    • [...a, ...b]

单页面应用与多页面应用