疫情期间的4次远程面试+答案整理

4,443 阅读22分钟

最近开始了久违的面试之旅,感觉金三银四感觉还是存在的。于是就想分享一下最近面试到的几家公司给大家,虽然也不是什么一线厂,但是问的问题感觉也有很多共通点,整理整理之后对前端面试也自信了许多。感觉把公司名字直接贴上来有点不是很尊重,就暂时隐去了。视频面试的题我面试完马上进行记录,电话面试的根据录音一点点整理出来的。希望能给大家一点帮助吧。

第一家公司

  • 社保参保人数:737
  • 公司行业:软件和信息技术服务业

1. 你用vue做了什么?

此处表示很迷惑,这个问题比较大范围。后来沟通之后才知道面试官想要问你最近用vue实现了一些什么功能,然后再根据你回答的内容进一步提问。

2. JSON.stringfy() JSON.parse() 有什么作用?有多少个参数?

JSON.stringify:有三个参数,第二个参数是对内容进行处理,第三个参数是设置缩进的值
str_pretty2 = JSON.stringify(str, null, 4)

JSON.parse():有两个参数,JSON.parse(text[, reviver])
JSON.parse('{"p": 5}', function (k, v) {
    if(k === '') return v;     // 如果到了最顶层,则直接返回属性值,
    return v * 2;              // 否则将属性值变为原来的 2 倍。
});                            // { p: 10 }

3. 如何实现一个深拷贝?

参考下面的连接,主要是把简单的思路讲清楚就好了。建议先自己整理一遍简单思路,不然讲出来会很乱。深拷贝实现

4. websocket的相关接口有哪些?

new Websocket('')
this.ws.onopen = ()=>{}
this.ws.onclose = ()=>{}
this.ws.onmessage = ()=>{}
this.ws.onerror = ()=>{}

5. 你知道的数组相关的API有哪些?

包括下一个答案的内容,还有pop、push、shift、unshift、slice、splice、reverse

6. 除了 for of,遍历数组还有哪些方法?

1.for循环
2.forEach循环
3.map循环
4.for of循环
5.filter循环
6.every遍历
7.some遍历
8.reduce累加器
9.reduceRight从末位计算的累加器
10.find
11.findIndex
12.keys、values、entries
13.while

7. 如何对下面数据实现过滤?

arr: [
  {
    key: '01',
    value: '西施'
  }, {
    key: '02',
    value: '王昭君'
  }, {
    key: '03',
    value: '杨玉环'
  }, {
    key: '04',
    value: '貂蝉'
  }, {
    key: '01',
    value: '西施'
  }, {
    key: '01',
    value: '西施'
  }
],
};

let finalResult = []
let attr = {}
for(let item of this.arr){
    if(!attr[item.key]){
      finalResult.push(item)
      attr[item.key]=true
    }
}

8. 你知道的ES6使用到的API有哪些?

略。一般你说什么就会更深入地问你。

9. Promise和Async的使用场景有哪些?

Promise和async/await常用的就是用来优化多重异步和异步嵌套,防止回调地狱。

加载文件、图片,接口需要先后顺序调用等。

10. 如何让前面两个接口其中一个返回了立马调用下一个接口?

Promise.race

const p = Promise.race([
  fetch('/resource-that-may-take-a-while'),
  new Promise(function (resolve, reject) {
    fetch('/resource-that-may-take-a-while2')
  })
]);

p
.then(console.log)
.catch(console.error);

11. 如果有五个接口同时调用怎么办?

const p = Promise.all([p1, p2, p3, p4, p5]);

12. vue路由如何做导航拦截?

router.beforeEach

13. vue组件通信方式有哪几种?跨组件一般怎么通信?

六种通信方式,基本上不用全答出来,常用的理解到就好。

14. vuex一般使用场景是什么?

vuex是一个专门为vue构建的状态管理工具,主要是解决多组建状态共享的问题。强调的是集中式管理。
常见场景:购物车的数据共享,登入注册

15. vue的destroy生命周期你一般怎么使用?怎么回收内存?

beforeCreated 一般用于写一个loading
created一般用于请求数据,可以将loading去掉
mounted之后与dom相关的操作,因为dom才解析完成之后才触发mounted beforeDestroy一般用于在移除组件的一些定时器,绑定的事件等

内存回收:
removeEventListener 用于移除事件
ClearTimeOut和ClearInterval 用于移除定时器

16. 如何动态加载组件?

VUE的动态加载组件

17. 纯前端如何控制权限?你们项目控制权限用的是什么方式?

参考链接。感觉大概答出来配合后端,在vue-router里面配合导航拦截就差不多了。

18. 下面数据如何结构赋值获取到line的第二个数据?

const node = {
    loc: {
      start: {
        line: [1,2,3],
        column: 5
      }
    }
};

let { loc: { start: {line:[,num]}} } = node;

19. webpack如何配置某个loader只遍历部分文件?

参考链接。配置loader中的include设置遍历范围。

20. webpack如何设置别名?

vuecli3.0里面在vue.config.js的文件里配置。
module.exports={
    chainWebpack:(config)=>{
        config.resolve.alias
        .set('@',resolve('./src'))
        //set第一个参数:设置的别名,第二个参数:设置的路径
    }
}

纯webpack的话,可参考:https://www.cnblogs.com/Jimc/p/10282969.html。

21. 你们后端用的是什么语言?你的项目是如何打包的?和后端一起打包的吗?

22. 你对不同版本的浏览器优化有了解吗?比如说将当前项目优化至一个特定的ie版本?

这块我不太了解,我只知道vue全家桶会将es6以上的用babel转换成es5可读的。

23. 版本管理工具用的是什么?

24. 最近有看什么书吗?

25. 你还有什么要问的?

第二家公司

  • 社保参保人数:200左右
  • 公司行业:教育行业

1. flex如何实现水平和垂直居中?改变主轴的API是什么?

justify-content属性定义了项目在主轴上的对齐方式。
.box {
  justify-content: flex-start | flex-end | center | space-between | space-around;
}

align-items属性定义项目在交叉轴上如何对齐。
.box {
  align-items: flex-start | flex-end | center | baseline | stretch;
}

主轴的方向
flex-direction: row | row-reverse | column | column-reverse;

2. 如何覆盖element的原生样式?

一、深度作用选择器( >>> )

<style scoped>
.box >>> .content {
  font-size:20px;
}
</style>
 二、/deep/ 预处理器less下使用

深度选择器/deep/与>>>作用相同

通过 >>> 可以使得在使用scoped属性的情况下,穿透scoped,修改其他组件的值

<style scoped lang="less">
.select {
     /deep/ .ivu-card-body {
        width: 100%;
      }
    }
</style>

3. 如何使多个元素相隔20px,但第一个元素保持不变?

div:not(:first-child){
    display:inline-block;
    margin-left:20px;
}

4. vue里面watch的作用,有什么其他参数吗?

观察 Vue 实例上的一个表达式或者一个函数计算结果的变化。
deep:true,为了发现对象内部值的变化
immediate:true ,将立即以表达式的当前值触发回调

5. computed的作用?computed和直接用一个函数进行属性计算的话,有什么区别?

计算属性是对属性值进行计算,会对原始值进行监听。 computed是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。 而一个函数进行计算显示的话每次刷新渲染都会重新执行函数。

6. 你知道有什么遍历数组的方法吗?

不重复回答。略

7. forEach和for循环的区别?

for循环可以进行中断而forEach不可以

8. 深拷贝和浅拷贝有什么不同?具体有什么实现方式?

浅拷贝:值的拷贝。
[...a],concat()

深拷贝:将具有地址的值拷贝至另外一个地址。
对象只有一层的话可以直接用Object.assign实现深拷贝。

9. JSON.stringify和JSON.parse实现深拷贝会有什么问题?

1、如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式。而不是时间对象;
2、如果obj里有RegExp、Error对象,则序列化的结果将只得到空对象;
3、如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失;
4、如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null;
5、JSON.stringify()只能序列化对象的可枚举的自有属性,例如:如果obj中的对象是有构造函数生成的,则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor;

10. let和var有什么差别?在let之前使用console.log打印一个在函数外的变量a,会有什么效果?

var tmp = 123;
if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}

VM34:4 Uncaught ReferenceError: Cannot access 'tmp' before initialization
    at <anonymous>:4:7

11. 函数和变量的提升会导致什么效果?

函数会被提升至最顶端。

1.
var tmp = 123;
function tmp (){}
console.log(tmp) ///123

2.
function tmp (){}
console.log(tmp)
var tmp = 123; /// f tmp() {}

函数提升要比变量提升的优先级要高一些,且不会被变量声明覆盖,但是会被变量赋值之后覆盖。

12. '等于'和 '全等'的区别?如何进行类型转换的?

当进行双等号比较时候: 
先检查两个操作数数据类型,
如果相同,则进行===比较,
如果不同,则愿意为你进行一次类型转换,转换成相同类型后再进行比较,
而===比较时, 如果类型不同,直接就是false.

如果已经是原始类型了,那就不需要转换了
如果需要转字符串类型就调用 x.toString(),转换为基础类型的话就返回转换的值。不是字符串类型的话就先调用 valueOf,结果不是基础类型的话再调用 toString
调用 x.valueOf(),如果转换为基础类型,就返回转换的值
如果都没有返回原始类型,就会报错

13. Promise内部的then是怎么实现的?如何实现.then的链式调用?

Promise 实例具有then方法,也就是说,then方法是定义在原型对象Promise.prototype上的。then方法返回的是一个新的Promise实例。因此可以采用链式写法,即then方法后面再调用另一个then方法。

14. 块级作用域是指哪些地方?

  • for循环
  • if判断的大括号
  • 函数内部

15. 箭头函数作用是什么?

箭头函数的一个用处是简化回调函数。

箭头函数有几个使用注意点。

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。

16. 如何对登录进行验证?

参考链接

17. 后端打包的话如果线上环境和测试环境的服务器地址不一样怎么处理?

参考链接

第三家公司

  • 社保参保人数:5000+
  • 公司行业:综合行业

1.请写两个方法,分别用递归 和 循环 两种方式实现 斐波那契求值: f(n)=f(n-1)+f(n-2), 要求函数输入任意自然数 n 后,返回该自然数的斐波那契数。

递归:

function f(n){
  if(n<=1){
      return n
  }
  return f(n-1)=f(n-2)
}

循环:

function f(n){
    if (n <= 1) return n;

    let first = 0;
    let second = 1;
    let result = 0;
    for (let i = 2; i <= n; i++)
    {
        result = first + second;
        first = second;
        second = result;
    }

    return result;
}

2.编码实现一下功能 sum(1)(2)()=3 sum(1)(2)(3)()=6 sum(2)=2 sum()=0

function sum() {
  let args = [...arguments];
  return function () {
    let inargs = [...arguments];
    if (arguments.length === 0) {
      let me = 0;
      for (let num of args) {
        me += num;
      }
      return me;
    }
    else
      return sum.apply(this, args.concat(inargs))
  };
}

3.用程序实现输入表达式 x = "1 2 + 2 + 5 4 + -", 输出该表达式的执行结果。逆波兰式,操作符置于操作数的后面。例如表达 “三加四” 时,写作 “3 4 +”而不是 “3+4”

function calc(expr) {
  if (!expr) return 0;  
  let arr = expr.split(' ')
  let elems = []
  let item;
  
  while (item = arr.shift()) { 
    if (!isNaN(+item)) {  
      elems.push(+item)
    } else {
      var res = count(item, elems.pop(), elems.pop())
      elems.push(res)
    }
  }

  function count (opera, num1, num2) {
    switch (opera) {
      case '+':
        return num2 + num1
      case '-':
        return num2 - num1
    }
  }
  return elems.pop()
}

4.实现一个 React 组件

//+ 有上下两部分,上面一个输入框,下面一个人名列表,可以使用 antd 组件,也可以不用,不同的话可以原生 input 和 ul li 来实现。当在 input 输入时,可以对列表中的数据进行实时的过滤。不输入的时候显示整个列表。 //+ 相应地,组件的 props 上有一个属性 names,用来接受人名。是一个 string 数组。比如 ['Zhang San', 'Li Si', 'Wang Wu', 'Zhao liu']。当我们输入字母 a 的时候,除了 'Li Si' 以外都会被过滤出来。因为他们都包含字母 a。

import React, { Component } from 'react';
import { Input, List } from 'antd';

const { Search } = Input;

class trash extends Component {
    constructor(props) {
        super(props);
        this.state = {
            listData: []
        };
        this.originData = []
        this.changeInput = this.changeInput.bind(this);
    }
    componentDidMount() {
        this.setState({
            listData: this.props.names
        });
        this.originData = this.props.names
    }
    componentDidUpdate(prevProps){
        if(prevProps.names!==this.props.names){
            this.setState({
                listData: this.props.names
            });
            this.originData = this.props.names
        }
    }
    changeInput(e) {
        let restData = this.originData.filter(item=>{
            return !item.includes(e.target.value)||!e.target.value
        })
        this.setState({
            listData: restData
        })
    }
    render() {
        const { listData } = this.state
        return (
            <div>
                <Search
                    placeholder="请搜索你要的名字"
                    onChange={this.changeInput}
                    style={{ width: 200 }}
                />
                <List
                    bordered
                    dataSource={listData}
                    renderItem={item => (
                        <List.Item>
                            {item}
                        </List.Item>
                    )}
                />
            </div>
        );
    }
}
export default trash;

5. 高阶函数了解吗?有用过来干什么?

接受另一个函数作为参数的函数称为高阶函数。如forEach、map等

6. 递归和循环的区别是什么?递归一般用来解决什么问题?

递归算法:

优点:代码简洁、清晰,并且容易验证正确性。

缺点: 1、它的运行需要较多次数的函数调用,如果调用层数比较深,每次都要创建新的变量,需要增加额外的堆栈处理,会对执行效率有一定影响,占用过多的内存资源。 2、递归算法解题的运行效率较低。在递归调用的过程中系统为每一层的返回点、局部变量等开辟了栈来储存。递归次数过多容易造成栈溢出等

循环算法:

优点:速度快,结构简单。

缺点:并不能解决所有的问题。有的问题适合使用递归而不是循环。如果使用循环并不困难的话,最好使用循环

7. react的生命周期有哪些?

8. flex的水平和垂直居中怎么实现的?如何让两个不等高的内容变得等高?

水平居中:
justify-content:center;
垂直居中:
align-items:center;

让两个内容变得等高:
align-items:stretch;

9. 解释一下原型链是什么意思?那es6里面的class和原型链有什么关系?

访问一个对象的属性时,先在基本属性中查找,如果没有,再沿着__proto__这条链向上找,这就是原型链。参考链接
Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。

10. 箭头函数的意义是什么?this指向哪里?

上面回答过了。

11. 你在工作中最觉得有意思的事情是什么?

12. 如果线上环境出问题了,你们项目目前的处理流程是怎样的?

1.找出是bug所在,找到对应错误日志 2.定位到错误的代码,修复 3.合并代码到release分支,测试通过 4.通过后再合并代码到master,上线。(前提要确保一切没问题,包括因为bug产生的数据会不会影响上线等等)

13. 阅读英文文档没问题的吧?

14. 你以后的前端发展方向是什么?

第四家公司

  • 社保参保人数:1000+
  • 公司行业:软件和信息技术服务业

1. 前端处理大量数据速度太慢如何解决?

优化算法、放到后端处理、或者用webworker也行

2. 你有做过响应式布局吗?具体的实现方式是什么?

参考链接

3. min-height和!important同时设置的话生效的会是什么呢?

min-height会先生效,覆盖掉!important

4. 重绘和回流是什么?什么会引起重绘?什么会引起回流?

当render tree中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流
不会影响布局的,比如background-color。则就叫称为重绘。

回流必将引起重绘,而重绘不一定会引起回流。 参考链接

5. 动画效果用js和css实现会有什么不同呢?

CSS动画 优点:

(1)浏览器可以对动画进行优化。

1、 浏览器使用与 requestAnimationFrame 类似的机制,requestAnimationFrame比起setTimeout,setInterval设置动画的优势主要是:1)requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。2)在隐藏或不可见的元素中requestAnimationFrame不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。

2、强制使用硬件加速 (通过 GPU 来提高动画性能)

(2)代码相对简单,性能调优方向固定

(3)对于帧速表现不好的低版本浏览器,CSS3可以做到自然降级,而JS则需要撰写额外代码

JS动画

(1)JavaScript动画控制能力很强, 可以在动画播放过程中对动画进行控制:开始、暂停、回放、终止、取消都是可以做到的。

(2)动画效果比css3动画丰富,有些动画效果,比如曲线运动,冲击闪烁,视差滚动效果,只有JavaScript动画才能完成

(3)CSS3有兼容性问题,而JS大多时候没有兼容性问题

缺点:

(1)JavaScript在浏览器的主线程中运行,而主线程中还有其它需要运行的JavaScript脚本、样式计算、布局、绘制任务等,对其干扰导致线程可能出现阻塞,从而造成丢帧的情况。

(2)代码的复杂度高于CSS动画

6. js有哪几种基本类型?

基本类型:
String、
Number、
Null、
Undefined、
Boolean、
Symbol、
BigInt

7. bigInt是哪个版本出现的?工作中有使用到吗?

es10

8. let和var声明变量的区别?var声明的变量会到window可以读取,那let可以吗?为什么

var 存在提升,我们能在声明之前使用。let、const 因为暂时性死区的原因,不能在声明前使用 var 在全局作用域下声明变量会导致变量挂载在 window 上,其他两者不会

let的不会挂载到window上,let命令所在的代码块内有效。

9. const和let的区别是什么?const声明的对象设置之后能改里面的内容吗?

const声明一个只读的常量。一旦声明,常量的值就不能改变。const的作用域与let命令相同:只在声明所在的块级作用域内有效。声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。

10. 引用类型和基本类型的储存区别是什么?

原始类型的数据值都是直接保存在“栈”中的,引用类型的值是存放在“堆”中的

11. 解释一下闭包是什么意思?

根据词法作用域的规则,内部函数总是可以访问其外部函数中声明的变量,当通过调用一个外部函数返回一个内部函数后,即使该外部函数已经执行结束了,但是内部函数引用外部函数的变量依然保存在内存中,我们就把这些变量的集合称为闭包。

12. js的垃圾回收机制是怎么工作的?

栈的话,出栈了,函数执行完返回了,ESP下移就会释放掉

堆的话: 在 V8 中会把堆分为新生代和老生代两个区域,新生代中存放的是生存时间短的对象,老生代中存放的生存时间久的对象。

  • 副垃圾回收器,主要负责新生代的垃圾回收:Scavenge 算法来处理。所谓 Scavenge 算法,是把新生代空间对半划分为两个区域,一半是对象区域,一半是空闲区域。...
  • 主垃圾回收器,主要负责老生代的垃圾回收

13. 循环数组有什么方法?

不重复回答。略

14. for of循环可以循环对象吗?for in可以循环一个数组吗?

for of循环不可以循环对象。一个数据结构只要部署了Symbol.iterator属性,就被视为具有 iterator 接口,就可以用for...of循环遍历它的成员。对象没有Symbol.iterator。 for in循环可以循环数组吗。可以,只能取到key。

15. for in循环出来的返回参数的值是什么?

for in取到的都是key值。

16. map的返回值是什么?是干嘛用的?

map返回一个处理后的数组

17. map的循环可以中断吗?

map的循环不能中断,不可设置break

18. forEach的返回值是什么?

返回undefined

19. 数组需要去重用什么方法?纯number的怎么去重?

分情况。new Set(数组)即可去重。

20. 深拷贝实现的大致思路是什么?用到递归的话为什么要对对象进行拷贝?

参考链接

21. 如果对象里面嵌套着同样的对象形成循环,那怎么解决?

参考链接

22. apply和call的作用和差别?

两者都是在fun函数运行时指定的this值,不同的是 fun.call(thisArg, arg1, arg2, ...) fun.apply(thisArg, [argsArray]) apply将函数的参数放在第二个参数用数组传入,call是逐个参数传入。

23. 箭头函数和普通函数的区别?箭头函数有arguments吗?

不重复回答。略。

24. 箭头函数可以用来作为构造函数吗?

不可以。因为箭头函数在创建的时候this就已经绑定了。

25. 函数的继承有什么其他的实现方法?

参考链接

26. 原型链继承或者构造函数继承是怎么实现的?

同上

27. 工厂代码如何进行继承?

同上上

28. Object.DefinedProperty怎么用的?有什么用?

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。 参考链接

29. vue3.x使用什么替代Object.DefinedProperty进行数据监听,Proxy有什么好处呢?

参考链接

30. Proxy的常用方法了解吗?

参考链接

31. map和set的使用场景有哪些?

Map适合储存键值对的数据 Set不保存重复的元素,检索元素效率低下,删除和插入效率高.

32. 平时对象的key值种类一般有哪些?

String、Symbol

33. weakSet和weakMap的场景了解吗?一般来说map的key值也可以是对象,那为什么要用weakMap?

WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别:
首先,WeakSet 的成员只能是对象,而不能是其他类型的值。
其次,WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用.

WeakMap结构与Map结构类似,也是用于生成键值对的集合。
WeakMap的键名所指向的对象,不计入垃圾回收机制。不使用时需手动删除。
WeakMap 与 Map 在 API 上的区别主要是两个:
一是没有遍历操作(即没有keys()、values()和entries()方法,也没有size属性。
二是无法清空,即不支持clear方法。

34. es6装饰器是什么概念?迭代器又是什么概念?

装饰器并未实装。装饰器(Decorator)是一种与类(class)相关的语法,用来注释或修改类和类方法。
遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。

35. 浏览器的事件循环机制是什么?

参考链接

36. 什么是典型的微任务?宏任务呢?先执行谁?

同上

37. vueRouter的路由模式有哪几种?每个模式的实现原理是什么?

配置路由模式:

hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器。
history: 依赖 HTML5 History API 和服务器配置。查看 HTML5 History 模式。
abstract: 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的。 API,路由会自动强制进入这个模式。

原理参考:juejin.cn/post/684490…

38. hash的路由变化要怎么监控?

参考链接

39. 跨域问题是怎么产生的?具体什么不同的接口才会产生跨域?

参考链接

40. 怎么处理跨域问题呢? 具体底层实现是怎么实现的呢?

同上

41. Jsonp是干什么用的呢?

参考链接

42. 浏览器缓存是怎么工作的呢?Http状态码什么时候会返回304?

43. webpack的常用的认识有哪些?

44. 项目中有用到过typeScript吗?

当前总结

一面的基础题比较高频出现的目前遇到的有

  • 跨域怎么实现的
  • 数组的操作
  • 深拷贝怎么实现的

有更多的面试经验再和大家分享吧~如果回答有问题的话欢迎指正~ 顺带点个赞呗哈哈。