# 目录

面试分为面试准备、基础知识面、进阶知识面、项目经验面、hr 面等几个阶段

下面就每个阶段需要准备哪些知识进行详解,希望每位同学都能拿到心仪的 offer!!!

本文已收录到以下个人网站和 github,欢迎 follow 和 star

# 面试准备

在开始面试前,我们首先得了解应聘的岗位的要求,并做针对性的准备。

准备包括以下几个方面:

  1. 职位描述(JD)分析
  2. 了解业务/项目
  3. 简历
  4. 自我介绍

# 职位描述(JD)分析

招聘网站上招聘的岗位都会有个职位描述,这个职位描述往往比较精简,以至于大家经常忽略了其深层的意义

下面的文章是比较好的分析范例,希望大家多多研究

# 了解业务/项目

分成两步:

  1. 了解业务,比如该公司主要经营机票业务,我们是不是应该了解一下机票的一个购买流程
  2. 了解项目,我们应该去了解该公司目前的项目,是 to B 还是 to C,是否有 m 站、海外站、小程序等,使用的是 vue 还是 react

# 简历

一份好的简历,给我们的面试加分不少。那怎样写出一份优秀的(至少是好的)简历呢?下面这些文章也许能够帮助到您。不需要每篇都看,参考一两篇即可!

# 简历模板

# 自我介绍

面试中第一个问题就是让我们自我介绍,准备好这个问题,能让面试官对我们有一个准确的了解,同时我们也可以通过自我介绍,引导面试官问出我们比较拿手的问题。

# 一面

侧重考察基础知识,这部分开始我们会准备一些面试中常遇到的问题

# CSS

# 使用 css 实现一个持续的动画效果

答案
animation:mymove 5s infinite;
@keyframes mymove {
from {top:0px;}
to {top:200px;}
}

主要考察

描述
animation-name 规定需要绑定到选择器的 keyframe 名称。。
animation-duration 规定完成动画所花费的时间,以秒或毫秒计。
animation-timing-function 规定动画的速度曲线。
animation-delay 规定在动画开始之前的延迟。
animation-iteration-count 规定动画应该播放的次数。
animation-direction 规定是否应该轮流反向播放动画。

扩展:

  • 使用 js 实现一个持续的动画效果
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>js动画</title>
    <style>
      #app {
        position: absolute;
        width: 300px;
        height: 300px;
        background-color: #f00;
      }
    </style>
  </head>
  <body>
    <div id="app"></div>
    <script>
      const end = 300,
        duration = 5;
      const $app = document.getElementById("app");
      let starttime;
      function move() {
        let percent = (((Date.now() - starttime) / 1000) % duration) / duration;
        $app.style.left = percent * end + "px";
      }
      // 方法一
      // function start() {
      //   starttime = Date.now()
      //   let timer = setInterval(() => {
      //     move()
      //   }, 1000/60);
      // }
      // start()

      // 方法二
      // function start() {
      //   let timer = setTimeout(() => {
      //     move()
      //     start()
      //   }, 1000/60);
      // }
      // starttime = Date.now()
      // start()

      // 方法三
      function start() {
        requestAnimationFrame(() => {
          move();
          start();
        });
      }
      starttime = Date.now();
      start();
    </script>
  </body>
</html>

# css3 新特性

# 如何清除浮动

答案
  1. clear
.floatfix{
    *zoom:1;
}
.floatfix:after{
    content:"";
    display:table;
    clear:both;
}
  1. BFC

注意事项:

  1. clear 只对块级元素有效

  2. clear 并不是清除了浮动效果,而是使当前元素盒子的边不能和前面的浮动元素 相邻。

扩展: 什么是BFC?BFC的好处是什么? 如何创建BFC?

# css 盒模型

答案

标准模型和 IE 模型

content padding border margin

# 四种定位的区别

答案
static 是默认值 不会创建BFC
relative 相对定位 相对于自身原有位置进行偏移,仍处于标准文档流中
absolute 绝对定位 相对于最近的已定位的祖先元素, 有已定位(指position不是static的元素)祖先元素, 以最近的祖先元素为参考标准。如果无已定位祖先元素, 以body元素为偏移参照基准, 完全脱离了标准文档流。
fixed 固定定位的元素会相对于视窗来定位,这意味着即便页面滚动,它还是会停留在相同的位置。一个固定定位元素不会保留它原本在页面应有的空隙。


# 其他

# html

# http

# http 的特点

答案
无状态 无连接

# http 报文的组成部分

答案
请求行 请求头 空行 请求体
转态行 响应头 空行 响应体

# http 的方法

答案
GET POST PUT DELETE HEAD

扩展:

  • GET 和 POST 的区别

# http 的状态码

答案

能记住以下几个就行

# http的持久化和管线化

了解概念即可,不必深究

https://www.cnblogs.com/hyzm/p/9530392.html

# DOM 事件类型

# 请问 DOM 事件级别

答案
DOM 0级: dom.onclick = function() {}
DOM 2级: document.addEventListener('click', ()=>{})
DOM 3级: document.addEventListener('keyup', ()=>{})

# DOM 事件模型

答案
捕获和冒泡

# DOM 事件流

答案
捕获>目标阶段>冒泡

# 描述 DOM 事件捕获的具体流程

答案
window>document>html>body>...

延伸:

  • 如何获取 html?

    答案
    document.documentElement
    

# Event 对象的常见应用

答案
event.preventDefault()
event.stopPropagation()
event.stopImmediatePropagation()
event.target
event.currentTarget

延伸:

# 自定义事件

可以用Event或CustomEvent

Event、CustomEvent 的区别是 CustomEvent 可以传参

// 首先需要提前定义好事件,并且注册相关的EventListener
var myEvent = new CustomEvent("event_name", {
  detail: { title: "This is title!" }
});
window.addEventListener("event_name", function(event) {
  console.log("得到标题为:", event.detail.title);
});
// 随后在对应的元素上触发该事件
if (window.dispatchEvent) {
  window.dispatchEvent(myEvent);
} else {
  window.fireEvent(myEvent);
}
// 根据listener中的callback函数定义,应当会在console中输出 "得到标题为: This is title!"

# fastclick 的作用是什么

答案
解决移动端点击300ms延迟

扩展:

# fastclick 原理

答案
利用event.preventDefault()阻止默认行为,然后派发自定义click事件

# js

# var let const 的区别

let 不存在变量提升,不能重复定义,会产生块级作用域,存在暂时性死区
const 声明就得赋值,变量的值不得改动

# 变量提升&作用域

# 获取字符串长度的方法

function codePointLength(text) {
  var result = text.match(/[\s\S]/gu);
  return result ? result.length : 0;
}

var s = "𠮷𠮷";

s.length; // 4
codePointLength(s); // 2
function length(str) {
  return [...str].length;
}

length("x\uD83D\uDE80y"); // 3

# 原型链

# This

# 闭包

# 继承

答案
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>面向对象</title>
  </head>
  <body>
    <script type="text/javascript">
      /**
       * 类的声明
       */
      var Animal = function() {
        this.name = "Animal";
      };

      /**
       * es6中class的声明
       */
      class Animal2 {
        constructor() {
          this.name = "Animal2";
        }
      }

      /**
       * 实例化
       */
      console.log(new Animal(), new Animal2());

      /**
       * 借助构造函数实现继承
       */
      function Parent1() {
        this.name = "parent1";
      }
      Parent1.prototype.say = function() {};
      function Child1() {
        Parent1.call(this);
        this.type = "child1";
      }
      console.log(new Child1(), new Child1().say());

      /**
       * 借助原型链实现继承
       */
      function Parent2() {
        this.name = "parent2";
        this.play = [1, 2, 3];
      }
      function Child2() {
        this.type = "child2";
      }
      Child2.prototype = new Parent2();

      var s1 = new Child2();
      var s2 = new Child2();
      console.log(s1.play, s2.play);
      s1.play.push(4);

      /**
       * 组合方式
       */
      function Parent3() {
        this.name = "parent3";
        this.play = [1, 2, 3];
      }
      function Child3() {
        Parent3.call(this);
        this.type = "child3";
      }
      Child3.prototype = new Parent3();
      var s3 = new Child3();
      var s4 = new Child3();
      s3.play.push(4);
      console.log(s3.play, s4.play);

      /**
       * 组合继承的优化1
       * @type {String}
       */
      function Parent4() {
        this.name = "parent4";
        this.play = [1, 2, 3];
      }
      function Child4() {
        Parent4.call(this);
        this.type = "child4";
      }
      Child4.prototype = Parent4.prototype;
      var s5 = new Child4();
      var s6 = new Child4();
      console.log(s5, s6);

      console.log(s5 instanceof Child4, s5 instanceof Parent4);
      console.log(s5.constructor);

      /**
       * 组合继承的优化2
       */
      function Parent5() {
        this.name = "parent5";
        this.play = [1, 2, 3];
      }
      function Child5() {
        Parent5.call(this);
        this.type = "child5";
      }
      Child5.prototype = Object.create(Parent5.prototype);
    </script>
  </body>
</html>

# 请问 new 执行的操作

1. 创建一个全新的对象。
2. 这个新对象会被执行 [[Prototype]] 连接。
3. 这个新对象会绑定到函数调用的 this。
4. 如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象。

# 你了解 Object.create 吗

# 二面

侧重考察知识面、高阶知识、深入原理等

# js

# setTimeout 和 setInterval 和 requestAnimationFrame

# JSON.parse(JSON.stringify())的缺点

在 JSON.stringify()阶段

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

6、如果对象中存在循环引用的情况也无法正确实现深拷贝

# 对象与数组的遍历

举个栗子

var a = { a: 1 };
var b = { b: 2 };
b.__proto__ = a;
Object.defineProperty(b, "c", {
  value: 3
});
b[Symbol()] = 4;

Object.keys(b); // ["b"]  返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性).

for (var i in b) {
  console.log(i, ":", b[i]);
} // b : 2 a : 1   循环遍历对象自身的和继承的可枚举属性(不含Symbol属性)

Object.getOwnPropertyNames(obj); // ["b", "c"] 返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性).
Reflect.ownKeys(b); // ["b", "c", Symbol()] 返回一个数组,包含对象自身的所有属性,不管属性名是Symbol或字符串,也不管是否可枚举.

# 什么是严格模式

严格模式主要有以下限制。

变量必须声明后再使用
函数的参数不能有同名属性,否则报错
不能使用with语句
不能对只读属性赋值,否则报错
不能使用前缀 0 表示八进制数,否则报错
不能删除不可删除的属性,否则报错
不能删除变量delete prop,会报错,只能删除属性delete global[prop]
eval不会在它的外层作用域引入变量
eval和arguments不能被重新赋值
arguments不会自动反映函数参数的变化
不能使用arguments.callee
不能使用arguments.caller
禁止this指向全局对象
不能使用fn.caller和fn.arguments获取函数调用的堆栈
增加了保留字(比如protected、static和interface)

# 设计模式

# 函数式编程

# 正则表达式

# es6

# 什么叫暂时性死区

在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。

# CommonJS 中的 require/exports 和 ES6 中的 import/export 区别?

- CommonJS 模块的重要特性是加载时执行,即脚本代码在 require 的时候,就会全部执行。一旦出现某个模块被”循环加载”,就只输出已经执行的部分,还未执行的部分不会输出。
- ES6 模块是动态引用,如果使用 import 从一个模块加载变量,那些变量不会被缓存,而是成为一个指向被加载模块的引用,需要开发者自己保证,真正取值的时候能够取到值。
- import/export 最终都是编译为 require/exports 来执行的。
- CommonJS 规范规定,每个模块内部,module 变量代表当前模块。这个变量是一个对象,它的 exports 属性(即 module.exports )是对外的接口。加载某个模块,其实是加载该模块的 module.exports 属性。
- export 命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。

# typescript

# vue

# vue-cli

vue响应式原理

# react

# 小程序

# taro

# weex

# 源码

# webpack

# 浏览器

# 网络请求

# 浏览器同源政策及跨域

五种方法

jsonp
hash
cors
websocket
postmessage

# 网络安全

1. XSS(cross-site-scripting, 跨站脚本)攻击

解决方法: 字符串转义

2. 跨站请求伪造(CSRF)

解决方法: 1.明文传递cookie
         2. 请求一个随机字符串(只能用一次)
         3. 判断referer

# 浏览器渲染机制

# js 运行机制

# 页面性能

# 进程与线程

# 页面渲染

# 缓存

# 垃圾回收

# 架构

# nodejs

# 算法

# 复杂度

# 二叉树

# 手写代码

# 手动实现 new

function New(Constructor, ...args){
    let obj = {};   // 创建一个新对象
    Object.setPrototypeOf(obj, Constructor.prototype);  // 连接新对象与函数的原型
    return Constructor.apply(obj, args) || obj;   // 执行函数,改变 this 指向新的对象
}

function Foo(a){
    this.a = a;
}

New(Foo, 1);  // Foo { a: 1 }

function _new() {
    let target = {}; //创建的新对象
    //第一个参数是构造函数
    let [constructor, ...args] = [...arguments];
    //执行[[原型]]连接;target 是 constructor 的实例
    target.__proto__ = constructor.prototype;
    //执行构造函数,将属性或方法添加到创建的空对象上
    let result = constructor.apply(target, args);
    if (result && (typeof (result) == "object" || typeof (result) == "function")) {
        //如果构造函数执行的结构返回的是一个对象,那么返回这个对象
        return result;
    }
    //如果构造函数返回的不是一个对象,返回创建的新对象
    return target;
}

# 实现深拷贝

# 防抖与节流

# 数组去重

# 实现一个简易版 vue2

# 其他

# 代码质量

# 工程化

# 三面

侧重考察以下能力

业务能力
团队协作能力
事务推动能力
带人能力
架构能力
项目经验

# 项目

面试官往往会让你说一说,都做过哪些项目,并就其中一两个深入了解。

我们需要从这些方面准备:

  1. 负责的项目做出了什么业绩
  2. 使用了什么技术方案
  3. 有什么技术难点
  4. 遇到了什么困难
  5. 收获了什么

# 架构与事务推动

  1. 是否自己搭建过项目?
  2. 你当时选择的技术栈是什么?
  3. 为什么这样选择?
  4. 讲讲遇到的困难
  5. 作为技术负责人你是怎么推动项目顺利进行的

# 带人与团队协作

  1. 是否带过人?
  2. 团队成员间怎样协作的?
  3. 是否有 code review?
  4. git 命令了解多少?
  5. 与后端、产品、设计、项目经理间是怎样协作的?

# 解决问题的能力

  1. 是否遇到过什么困难,你是怎么解决的?
  2. 你平时都是怎样学习的?
  3. 你平常都上哪些网站?

# 对技术的热情

  1. 你是否了解 vue3?vue3 做了哪些优化?与 vue2 有什么不同?
  2. 你是否了解微服务?web component? http3?等
  3. 是否有开源项目?

# 终面(hr 面)

侧重考察性格、潜力

到了这一面,offer 基本已经到手了,但也不可掉以轻心,因为 hr 往往有一票否决权。

可以参考

# 这面需要我们展现以下特性:

  1. 乐观积极
  2. 主动沟通
  3. 逻辑顺畅
  4. 上进有责任心
  5. 有主张,做事果断

# 可能会有以下问题:

  1. 对加班的看法
  2. 职业规划是什么
  3. 你有什么要问的
  4. 你大学都参加了什么社团
  5. 你平时都喜欢干什么
  6. 如果和同事有了冲突,你会怎么办

至此面试结束,恭喜你拿到了心仪的 offer!

接下来要讲的是面试技巧以及经验,以帮助大家更好的应对面试!!!

# 面试技巧

# 如果你是面试官

# 面试经验

# 阿里

# 腾讯

# 百度

# 京东

# 小米

# bilibili

# 头条

# 拼多多

# 其他

# 招聘官网

# 内推

# 待遇


# 面试题仓库

  • https://github.com/kdn251/interviews/blob/master/README-zh-cn.md
  • https://github.com/jwasham/coding-interview-university/blob/master/translations/README-cn.md([译] Coding Interview University 一套完整的学习手册帮助自己准备 Google 的面试)
  • https://github.com/haizlin/fe-interview
  • https://github.com/30-seconds/30-seconds-of-interviews
  • https://github.com/xiaomuzhu/front-end-interview
  • https://github.com/yisainan/web-interview
  • https://github.com/woai3c/Front-end-basic-knowledge
  • https://github.com/qiu-deqing/FE-interview
  • https://github.com/poetries/FE-Interview-Questions
  • https://github.com/azl397985856/fe-interview