吐血整理2020年前端面经(一)

796 阅读7分钟

前言:今年受疫情影响,大多数企业都收缩了HC,有的企业甚至关门大吉。这样的情境下,找工作就变得比往年困难。但是,只要你不断努力,消掉自我怀疑情绪,工作总会有的,相信我!我搜集了腾讯、快手、头条、美团、滴滴等各大公司的前端面试题整理成知识点,有自己亲身经历的,也有身边朋友分享给我的。希望对正在找工作的你有所帮助,也衷心的祝愿大家都能找到心仪的工作。

一、项目地址

github.com/webharry/fe…

二、面试题集锦

javascript基础知识点及常考面试题

1、let、const、var 的区别?

let 和 const 定义的变量不会出现变量提升,而 var 定义的变量会提升。
let 和 const 是JS中的块级作用域
let 和 const 不允许重复声明(会抛出错误)
let 和 const 定义的变量在定义语句之前,如果使用会抛出错误(形成了暂时性死区),而 var 不会。
const 声明一个只读的常量。一旦声明,常量的值就不能改变(如果声明是一个对象,那么不能改变的是对象的引用地址)

一道鹅厂面试题:问输出什么?

for(var i = 0; i < 10; i++) {
    setTimeout(() => {
        console.log(i)
    }, 0)
}

结果:输出10个10. 解决方案有哪些? (可以使用let替换var、或者使用闭包)

2、typeof、instanceof 的区别?instanceof 的实现原理是什么?

typeof:
能够正确判断基本类型,null除外, 'tyoeof null' 输出为 'object'。
不能正确的判断引用类型,typeof 应用于函数输出 'function',除此之外,输出的全是 object。

instanceof:
可以准确的判断复杂数据类型,但是不能正确判断基本数据类型。

instanceof 是通过原型链判断的,A instanceof B, 在A的原型链中层层查找,是否有原型等于B.prototype,如果一直找到A的原型链的顶端(null;即Object.proptotype.__proto__),仍然不等于B.prototype,那么返回false,否则返回true.

移步我的博客:instanceof原理

3、ES6中的 class 和ES5的类有什么区别?

我的博客:浅谈ES5,ES6继承

4、js同步异步的理解

我的博客:了解JavaScript执行机制

5、this的指向

我的博客:this指向的4种场景

6、call、apply、bind的区别,内部原理?

我的博客:Javascript中的apply、call和bind

7、new操作符原理

new 操作符的工作原理:

1、创建一个空对象,var obj = {};
2、将新创建对象obj的__proto__指向构造函数原型prototype
3、将新对象obj作为调用上下文,执行构造函数
4、如果构造函数中没有返回其它对象,那么返回新创建对象obj,否则返回构造函数的返回值

8、谈谈你对原型和原型链的理解?附上一道鹅厂的题:

var foo = {},
    F = function(){};
Object.prototype.a = 'value a';
Function.prototype.b = 'value b';

console.log(foo.a)   
console.log(foo.b)    
console.log(F.a)      
console.log(F.b)  

输出结果:

console.log(foo.a)  // value a
console.log(foo.b)  // undefined  
console.log(F.a)    // value a   
console.log(F.b)    // value b

这题考察原型链知识,理解原理移步我的博客-:原型链

9、深拷贝和浅拷贝区别?

浅拷贝:只是复制对象的第一层属性,如果对象的属性是引用类型时,实质复制的是其引用,只要引用指向的值改变就会跟着改变
深拷贝:对于对象中的属性进行递归复制,如果对象的属性是引用类型时进行递归,直到递归至基本类型时进行赋值,深拷贝的对象不随源对象变化。

实现一个深拷贝:

function deepClone(obj) { //递归拷贝
    if(obj === null) return null; //null 的情况
    if(obj instanceof RegExp) return new RegExp(obj);
    if(obj instanceof Date) return new Date(obj);
    if(typeof obj !== 'object') {
        //如果不是复杂数据类型,直接返回
        return obj;
    }
    /**
     * 如果obj是数组,那么 obj.constructor 是 [Function: Array]
     * 如果obj是对象,那么 obj.constructor 是 [Function: Object]
     */
    let t = new obj.constructor;
    for(let key in obj) {
        //如果 obj[key] 是复杂数据类型,递归
        t[key] = deepClone(obj[key]);
    }
    return t;
}

10、防抖和节流的实现

防抖(debounce): 指定时间内频繁触发事件,则时间清零重新计时,只有当触发频率超过指定时间间隔才会执行函数。
节流(throttle): 一段时间内只会执行一次函数。

防抖实现:

function debounce(func, wait, immediate = true) {
    let timer;
    // 延迟执行函数
    const later = (context, args) => setTimeout(() => {
        timer = null;// 倒计时结束
        if (!immediate) {
            func.apply(context, args);
            //执行回调
            context = args = null;
        }
    }, wait);
    let debounced = function (...params) {
        let context = this;
        let args = params;
        if (!timer) {
            timer = later(context, args);
            if (immediate) {
                //立即执行
                func.apply(context, args);
            }
        } else {
            clearTimeout(timer);
            //函数在每个等待时延的结束被调用
            timer = later(context, args);
        }
    }
    debounced.cancel = function () {
        clearTimeout(timer);
        timer = null;
    };
    return debounced;
};

节流实现:

//underscore.js
function throttle(func, wait, options) {
    var timeout, context, args, result;
    var previous = 0;
    if (!options) options = {};

    var later = function () {
        previous = options.leading === false ? 0 : Date.now() || new Date().getTime();
        timeout = null;
        result = func.apply(context, args);
        if (!timeout) context = args = null;
    };

    var throttled = function () {
        var now = Date.now() || new Date().getTime();
        if (!previous && options.leading === false) previous = now;
        var remaining = wait - (now - previous);
        context = this;
        args = arguments;
        if (remaining <= 0 || remaining > wait) {
            if (timeout) {
                clearTimeout(timeout);
                timeout = null;
            }
            previous = now;
            result = func.apply(context, args);
            if (!timeout) context = args = null;
        } else if (!timeout && options.trailing !== false) {
            // 判断是否设置了定时器和 trailing
            timeout = setTimeout(later, remaining);
        }
        return result;
    };

    throttled.cancel = function () {
        clearTimeout(timeout);
        previous = 0;
        timeout = context = args = null;
    };

    return throttled;
};

11、ES6新的特性有哪些?

块级作用域(let,const)、基本数据类型Symbol
定义类的语法糖(class)
变量的解构赋值
箭头函数、函数参数允许设置默认值,引入了rest参数
数组新增了一些API,如 isArray / from / of 方法;数组实例新增了 entries(),keys() 和 values() 等方法
对象和数组新增了扩展运算符
ES6 新增了模块化(import/export)
ES6 新增了 SetMap 数据结构
ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例
ES6 新增了生成器(Generator)和遍历器(Iterator)

参看ES6 入门教程-阮一峰

12、对promise的理解,手写代码

我的博客-手撸Promise

13、打开一个网页浏览器做了哪些工作

这道题是面试中的高频题,可以考察的知识点非常多。主要包括了以下几个流程:

  • 浏览器的地址栏输入URL并按下回车。
  • 浏览器查找当前URL是否存在缓存,并比较缓存是否过期。
  • DNS解析。
  • 建立TCP连接(三次握手)。
  • HTTP发起请求。
  • 服务器处理请求,浏览器接收HTTP响应。
  • 渲染页面,构建DOM树。
  • 关闭TCP连接(四次挥手)。

再针对每个过程进行详细考察。

(1)DNS解析过程,网上找了一张图,过程画的比较直观清晰:

(2)浏览器渲染过程

移步我的博客:浏览器渲染过程

(3)TCP的三次握手和四次挥手过程?

(4)你知道HTTP哪些状态码?

1xx:指示信息–表示请求已接收,继续处理。
2xx:成功–表示请求已被成功接收、理解、接受。
3xx:重定向–要完成请求必须进行更进一步的操作。
4xx:客户端错误–请求有语法错误或请求无法实现。
5xx:服务器端错误–服务器未能实现合法的请求。
平时遇到比较常见的状态码有:200, 204, 301, 302, 304, 400, 401, 403, 404, 422, 500(分别表示什么请自行查找)。

(5)浏览器缓存和缓存原理 详细参看博客:

三、面试技巧

我认为对于技术面试,除了准备基础知识点外,也需要准备一些面试技巧,下面列出我网上找的有参考价值的帖子:

面试官到底想看什么样的简历?

面试流程

2020年8月-9月前端找工作感受总结

四、写在最后

本文梳理了JavaScript的基础知识面试题,后续还会梳理出算法、框架等的面试题,持续更新中。。。 如果本文给了您一点帮助或者是启发,请不要吝啬你的赞和Star,您的肯定是我前进的最大动力。