整理一下最近前端面试的题目

1,680 阅读7分钟

最近走访了几家互联网公司,在此整理下面试题目,希望对大家有用

面试先开始都是先做个一分半钟的自我介绍,重点突出下自己的技术栈和一两个项目,捡自己最熟悉的地方重点讲一下. 然后面试官基本都会着重问一下你参与项目里的细节.这一段大家各自发挥,没什么好说的. 聊完项目,面试官会考察应试者的前端基本功,下面是我整理的最近几家公司的面试题.

一. 前端基础题

  1. 有多少种方式可以让盒子垂直居中对齐
  2. flex-shrink:0和flex-grow:0是什么意思
  3. es6有哪些新特性
  4. 防抖和节流的区别是什么
  5. 不用es6 flat扁平化多维数组
  6. 去重一个数组,这个数组里每个元素都是对象
  7. 解释一下原型链
  8. 什么是函数式编程?js里还有什么编程范式
  9. 写一个函数实现instanceof
  10. 写一个函数实现交通灯系统
  11. 求和斐波那契数列,并做适当的优化
  12. forEach和map区别是什么
  13. 哪些数组方法会改变原数组
  14. 手写js柯里化函数
  15. this的指向有哪些
  16. 手写instance函数
  17. 网站性能优化有哪些?
  18. 强缓存和协商缓存
  19. http状态码有哪些?分别是什么意思
  20. 跨域的解决方案
  21. react生命周期顺序及性能优化
  22. react函数式组件和类组件的区别
  23. react父子组件通信
  24. setState什么时候是同步的?为什么要设计成异步
  25. react类组件super关键字的作用是什么? static关键字呢
  26. 常用的react hooks有哪些?分别代表什么意思
  27. 为什么不能条件使用react hooks
  28. react服务端渲染的原理是什么
  29. react map不加key会有什么影响,如果加一个随机key呢
  30. 什么是副作用,为什么说函数式组件没有副作用
  31. 为什么虚拟dom比真实dom快
  32. react相对于原生js的优势有哪些
  33. react diff和fiber算法的区别是什么
  34. 如何实现tooltip组件,组件式调用和方法调用有何不同,了解portal吗
  35. redux的数据流工作流程
  36. redux中间件用过哪些
  37. 项目中redux最佳实践有哪些
  38. webpack-dev-server的原理是什么
  39. 什么是babel-preset-env,babel-plugin-transform和babel-polyfill
  40. post请求和put请求的区别
  41. 手写nodejs如何遍历文件夹下的所有文件
  42. 对express中间件的理解
  43. 中台有哪些特点?解决了什么问题
  44. 一次最稳妥的git上传代码的流程是什么
  45. git rebase和git reset的区别是什么
  46. 大boss喜欢问的问题: 场景设计或给出解决方案

二. 编程问答题

1. 下面这段代码将会输出什么?简单解释一下

    let n = [10, 20]
    let m = n;
    let x = m;
    m[0] = 100;
    x = [30, 40];
    x[0] = 200;
    m = x;
    m[1] = 300;
    n[2] = 400;
    console.log(n, m, x) 

2. 下面这段代码会有什么问题? 如果有请指出

    var promise1 = function(){
        return new Promise((res, rej) => {
            a.b = 'c'
            res()
        })
        .catch((err) => Promise.reject(err))
    }
    async function fun(){
        await promise1()
        console.log("1111")
        ... //后面还有业务逻辑
    }
    fun()

3. 下面这段异步代码输出结果是什么?

    console.log('script start');

    const dog = new Promise(function(resolve) {
        console.log('dog1');
        resolve();
        console.log("promiseResolve")
    }).then(function() {
        console.log('dog2');
        return "dog"
    }).then(console.log("dog end"));

    const cat = new Promise(function(resolve) {
        console.log('cat1');
        resolve();
        setTimeout(() => {
            console.log('setTimeout1')
        })
    }).then(function() {
        console.log('cat2');
        return "cat"
    })

    setTimeout(function() {
        console.log('setTimeout2');
    }, 0)

    console.log("before promise.race")

    Promise.race([dog, cat])
        .then((one, two) => {
            console.log("one", one)
            console.log("two", two)
        })
        .catch(err => {
            console.error('err', err);
        })
    
    console.log('script end');

4. 下面这段异步代码输出结果是什么?

    async function async1() {
        console.log('async1 start');
        await async2();
        console.log('async1 end');
    }
    
    async function async2() {
        new Promise(function(resolve) {
            console.log('promise1');
            resolve();
            console.log("promiseResolve")
        }).then(function() {
            setTimeout(function() {
                console.log('setTimeout1');
            })
            console.log('promise2');
        });
    }
    
    console.log('script start');
    
    setTimeout(function() {
        console.log('setTimeout2');
    }, 0)
    
    async1();
    
    process.nextTick(() => {
        console.log("nextTick");
    })
    
    new Promise(function(resolve) {
        console.log('promise3');
        resolve();
        setTimeout(() => {
            console.log('setTimeout3')
        })
    }).then(function() {
        console.log('promise4');
    })
    .then(() => console.log('promise5'))
    .then(() => console.log('promise6'))
    
    console.log('script end');

5. 下面这段代码输出结果是什么?假如最后输出的结果不是我们想要的,怎么改

    const arr = [1,2,3,4,5,6]
    arr.forEach(async (item) => {
        await sleep(item)
        console.log('after', item)
    })
    function sleep(item){
        return new Promise(res => {
            setTimeout(() => {
                res(console.log('before', item))
            }, 2000)
        })
    }

6. 下面这段异步代码输出结果是什么?

const queue = [1,2,3,4]
function func(){
    return new Promise(async res => {
        await sleep()
        res(queue[0])
        if(queue.shift()){
            return func()
        }
    })
}

function sleep(){
    return new Promise(res => {
        setTimeout(() => res(), 2000)
    })
}

func()
    .then((result) => {
        console.log('result', result)
    })

6. 下面这段异步代码输出结果是什么?

function a(){
    return new Promise(res => {
        console.log(3)
        setTimeout(() => {
            console.log(4)
            res()
        }, 2000)
    })
}

function b(){
    return new Promise(async res => {
        console.log(1)
        res()
        console.log(2)
        await a()
        console.log(5)
    })
}

b().then(() => {
    console.log(6)
})

7. 下面这段异步代码输出结果是什么?

new Promise(res => {
    setTimeout(() => {
        console.log(1)
        res()
    })
    console.log(2)
})
console.log(3)

二. 大厂笔试题

字节跳动

1. 有N个请求,每次发送一个,如果有一个失败了,就不再执行后面的请求并返回直到上一个请求的所有结果,否则返回所有结果

// 我这里用异步宏任务模拟请求
const result = []
const arr = [1,2,3,4,5,6,7]
function call(data){
  return new Promise((res, rej) => {
    setTimeout(() => {
      if(data === "5"){
        rej(data)
      } else {
        res(data)
      }
    }, 1000)
  })
}
function foo(){
  return call(arr.splice(0, 1).join(""))
    .then((response) => {
      console.log("response", response)
      result.push(response)
      if(arr.length){
        return foo()
      } else {
        console.log("result", result)
        return result
      }
    })
    .catch(err => {
      console.log("result", result)
      return result
    })
}
foo()

2. 写一段柯里化函数实现下面的功能

function add(a, b, c){
  return a+b+c
}
curry(add)(1)(2)(3)
curry(add, 1)(2)(3)
curry(add, 1, 2)(3)
curry(add, 1, 2, 3)
// 答案
function curry(func, ...args1){
  let arr = [...args1]
  if(func.length <= args1.length){
    return func.apply(this, args1)
  } else {
    const foo = function(...args2){
      arr = [...arr, ...args2]
      if(func.length <= arr.length){
        return func.apply(this, arr)
      } else {
        return foo
      }
    }
    return foo
  }
}
console.log(curry(add, 1, 2, 3))

头条面试官还出了一道关于数据结构的算法题,我对数据结构不是很了解,心想如果下次再遇到数据结构的算法题,打算直接说不会

阿里巴巴

1. 请使用 html + css 实现以下效果,且不管浏览器如果缩放,始终保持下图在浏览器水平和垂直方向的中间(十字架需css绘制)

img.alicdn.com/tfs/TB1Ogml…

<html lang="en">
<head>
	<meta charset="utf-8" />
	<title>align</title>
	<style type="text/css">
		.container{
            display: flex;
            align-items: center;
            justify-content: center;
            flex-direction: column;
            height: 100%;
            width: 100%;
            background-color: #ccc;
        }
        .top{
            width: 30px;
            height: 50px;
            background-color: #fff;
            border: 2px solid blue;
            border-bottom: 0;
        }
        .middle{
            display: flex;
            background-color: #fff;
        }
        .left, .right{
            width: 50px;
            height: 30px;
            background-color: #fff;
        }
        .left{
            border: 2px solid blue;
            border-right: 0;
            margin-right: 15px;
        }
        .right{
            border: 2px solid blue;
            border-left: 0;
            margin-left: 15px;
        }
        .bottom{
            width: 30px;
            height: 50px;
            background-color: #fff;
            border: 2px solid blue;
            border-top: 0;
        }
	</style>
</head>
<body>
	<div class="container">
        <div class="top"></div>
        <div class="middle">
            <div class="left"></div>
            <div class="right"></div>
        </div>
        <div class="bottom"></div>
    </div>
</body>
</html>

2. 实现以下函数 /**

  • 说明:实现一个方法,用于比较两个版本号(version1、version2)
  • 如果version1 > version2,返回1;如果version1 < version2,返回-1,其他情况返回0
    
  • 版本号规则`x.y.z`,xyz均为大于等于0的整数,至少有x位
    
  • 示例:
  • compareVersion('0.1', '1.1.1'); // 返回-1
  • compareVersion('13.37', '1.2 '); // 返回1
  • compareVersion('1.1', '1.1.0'); // 返回0 */
// 答案
 function compareVersion(version1, version2){
   const version1Arr = version1.split(".")
   const version2Arr = version2.split(".")
   const length = Math.max(version1Arr.length, version2Arr.length)
   for(let i=0; i < length; i++){
       if(i<(length-1)){
           if(Number(version1Arr[i]) > Number(version2Arr[i])){
               return 1
           } else if(Number(version1Arr[i]) < Number(version2Arr[i])){
               return -1
           } 
       } else {
           const firstThird = version1Arr[length-1] || 0
           const SecondThird = version2Arr[length-1] || 0
           if(firstThird > SecondThird){
               return 1
           } else if(firstThird < SecondThird){
               return -1
           } else {
               return 0
           }
       }
   }
}

3. 有一个对象X,内容如下,请写程序找出所有d的值

const X = {
  y: {
    c: {
      d: 1
    }
  },
  z: {
    e: {
      d: 2
    }
  },
  q: {
    f: {
      d: 3
    }
  },
  o: {
    m: {
      g: {
        h: {
          d: 4
        }
      }
    }
  }
}
// 答案
const resultArr = []
function lookup(obj){
    for(let i in obj){
        if(Object.prototype.toString.call(obj[i]) === '[object Object]'){
            lookup(obj[i])
        } else if(i === "d"){
            resultArr.push(obj.d)
        }
    }
}
lookup(X)
console.log("resultArr", resultArr)

4. 实现以下功能,已知有 N 个 url,每次最多可并行请求 M,尽快完成对 N 个 url 的请求并保存所有返回结果到数组中。(每次发M个请求,每完成一个请求就发送一个剩下的请求)

    const urls = ["1", '2', '3', '4', '5', '6', '7']
    const results = []
    const promises = []
    function getData(url) {
        return fetch(url)
            .then((response) => {
                results.push(response)
                if(urls.length) {
                    return getData(urls.splice(0, 1).join(""))
                }
            })
    }
    urls.splice(0, M).forEach(item => {
        promises.push(getData(item))
    })
    Promise.all(promises)
        .then(() => {
            console.log('results', results)
        })

如有好的见解,欢迎在评论区交流.