2020年前端面试题总结(二)

635 阅读3分钟

楼主因为项目大多数都是微服务架构node做中间层的这种设计,类似于eggjs,所以node问的相对多一点。另外,感觉业务方向偏向比较严重,场景题目比较多,项目难点以及亮点必问。

2020年前端面试题总结(一)

一面

1.ES6的三点扩展运算符了解吗?
2.三点扩展运算符能够解析对象和字符串吗?
  • Iterator接口

  • Symbol.iterator

  • 对象的浅拷贝 eg: react的写法 {...props}

3.箭头函数了解吗?
  • 简化函数写法

  • this函数定义时候

  • arguments/caller

  • 不能用作构造函数,new

  • 不能用作generator函数

4.熟悉Set和Map吗
  • 顺便说了WeakSet和WeakMap的弱引用及其简单的垃圾回收
5.说下垃圾回收
  • 自己挖坑...
6.说下原型链
  • 记住,一定要吃透这块 prototype/constructor/proto

7.熟悉Vue吗

两年没写了,所以只知道发布订阅+属性劫持

8.如何属性劫持
  • Object.defineProperty

  • Reflect.defineProperty

9.写一个发布订阅模式
  • 写了node的EventEmitter类
10.实现一个函数,找到数组中的两相和等于某个值
  • leecode题目
11.删除数组中连续重复的数

eg: [1,1,2,3,4,3,3,3,5,5] 结果为 [1,2,3,4,3,5]

  • 新数组的最后一项与老数组for对比

  • 快慢指针

const arrayDeduplication = function(arr){
    const res = [arr[0]];
    for(let i=1; i<arr.length; i++){
        if(res[res.length-1] !== arr[i]){
            res.push(arr[i])
        }
    }
    return res;
}

const arrayDeduplication = function(arr){
    let low = quick = 0;
    while(quick < arr.length){
        if(arr[low] === arr[quick]){
            quick++;
        }else{
            arr[++low] = arr[quick++]
        }
    }
    return arr.slice(0, low+1);
}
console.log(arrayDeduplication([1,1,2,3,4,3,3,3,5,5]))
12. react的优化点
13. 说下react的Fiber树
14. 说下React的Fiber Schedule
15. 说下函数式组件的好处
16. 说下Wbepack的优化点
17. 说下setState是同步还是异步
18. 出了一道react合成事件的题目

下面的组件点击内部按钮如何打印

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {

        };
        this.container = React.createRef();
        this.inner = React.createRef();
    }

    componentDidMount() {
        document.documentElement.addEventListener('click', () => {
            console.log('原生document');
        }, true);
        document.body.addEventListener('click', () => {
            console.log('原生body');
        }, true);
        this.container.current.addEventListener('click', () => {
            console.log('原生container');
        }, true);
        this.inner.current.addEventListener('click', () => {
            console.log('原生inner');
        }, true);
    }

    containerHandle() {
        console.log('外盒子合成事件');
    }

    innerHandle(e) {
        web.reportPv();
        console.log('内盒子合成事件');
        // e.stopPropagation()
    }

    render() {
        return (
            <div className="container" onClickCapture={this.containerHandle} ref={this.container}>
                <div className="inner" onClickCapture={this.innerHandle} ref={this.inner} />
            </div>
        );
    }
}

理解react的合成事件和事件挂载

19.React的hook可以写在条件语句里面吗

理解hook原理

20. 实现个instanceof
21. 实现个bind方法
22. 实现下Promise.allSettled

二面

1. 说下事件循环机制
2. 说下浏览器原理
  • html树-> cssom树 -> 渲染树 -> 分层树 -> 绘制列表 -> 光栅化 -> 渲染页面

  • 重排,重绘以及合成

3. 比如有1万个ajax请求,用promise实现让其并发量每次最多十个
class AsyncAjax {
    public maxConcurrentNums:number

    private queue:Array<SkyEyeType.ReportAjaxParams>

    public constructor(maxConcurrentNums = 10) {
        this.maxConcurrentNums = maxConcurrentNums;
        this.queue = [];
    }

    public addReport(task:SkyEyeType.ReportAjaxParams) {
        this.queue.push(task);
        this._run();
    }

    private _sendAjax(options:SkyEyeType.ReportAjaxParams) {
        let xhr = null;
        if (window.XMLHttpRequest) {
            xhr = new window.XMLHttpRequest();
        } else {
            xhr = new window.ActiveXObject('Microsoft.XMLHTTP');
        }
        return new Promise((resolve, reject) => {
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    const { status } = xhr;
                    if (status < 200 || status > 300) {
                        reject(new Error('webReport error!'));
                    } else {
                        resolve('ok');
                    }
                }
            };
            xhr.open('POST', options.url, true);
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
            xhr.send(JSON.stringify(options.data));
        });
    }

    private _run() {
        const len = this.queue.length;
        if (len === 0) return;
        const mixNum = Math.min(len, this.maxConcurrentNums);
        for (let i = 0; i < mixNum; i += 1) {
            this.maxConcurrentNums -= 1;
            const options = this.queue.shift();
            this._sendAjax(options).then((val) => {
                this.maxConcurrentNums += 1;
                this._run();
                return val;
            }, (err) => {
                this.maxConcurrentNums += 1;
                this._run();
                return Promise.reject(err);
            }).catch(() => {});
        }
    }
}
4. 说下module.exports和exports区别
5. node实现多进程的方式有哪些
6. webpack优化点有哪些
7. 变量提升问题
f();
function f(){
    console.log(1);
}
var f = function(){
    console.log(2);
}
f();

说下打印结果和原因

8. 算法,拆分数组中连续的数字,生成二维数组

例如:[1,2,3,3,4,1,5,6] 返回 [[1,2,3],[3,4],[1],[5,6]]

让我用了两种方法实现,都完美跑通。

9. 算法,输入n打印菱形

例如:输入4,打印

   *
  * *
 *   *
*     *
 *   *
  * *
   *
const print = function(n) {
    const tag = '*';
    let leftPad = 0, midPad = -1;
    for (let i = 0; i < 2*n-1; i++) {
        if(i === 0 || i === 2*n-2){
            leftPad = n-1;
            console.log(`${' '.repeat(leftPad)}*`);
        }else{
            if(i < n){
                leftPad--;
                midPad += 2;
            }else{
                leftPad++;
                midPad -= 2;
            }
            console.log(`${' '.repeat(leftPad)}*${' '.repeat(midPad)}*`);
        }
    }
}

有更加好的方法可以留言,我瞎写的一个

三面

1. 说下微服务
2. 说下路由美化的原因
3. 说一下微服务和分布式的差异性及其优缺点
4. 如何解决跨域
5. window.onerror和window.addEventListener('error')区别
6. 如何计算白屏时间
7. 如何统计PV/UV
8. 说一下虚拟DOM

说完让我将字符串版本的html写个函数转换为虚拟dom(懵逼ing)

9. 说一下react的diff算法

其实也就数组类型的调和子节点比较难一点

10. 算法:实现一个函数求字符串的最长无重复的连续字符串

例如:str='abccbacb' 输出 'abc'

11. 算法:给出一个四个数字的数组,找出能够生成的最大时间,没有则返回null

例如:[1,2,4,9] 返回 21:49