我的前端2019面试指引

572 阅读5分钟

当然也可以看我的 github 的 issues 欢迎 star!

前言

其实,现在已经总结的够多了,大家可以看看:

  1. 总结了17年初到18年初百场前端面试的面试经验(含答案)
  2. (中篇)中高级前端大厂面试秘籍,寒冬中为您保驾护航,直通大厂以及上篇都挺不错的
  3. JavaScript 算法
  4. 一个合格的中级前端工程师必须要掌握的 28 个 JavaScript 技巧

但是看过了还是很容易就忘了,还是得自己敲一遍好。就总结一些自己有问题的地方吧

自己遇到以及整理的一些点:

1. this 的指向:

const a = {
  count:1,
  b:{
    count: 2,
    getCount: function(){
      console.log(this.count);
    }
  }
}

const getb = a.b.getCount
console.log(getb())
console.log(a.b.getCount()) // 这里要注意不要被迷惑了 

理解的话,首先要明确的是 this 是在函数里面,在函数调用时动态指定的,指向当前函数(方法)的执行栈(上下文)。 可以查看 理解 JavaScript 中函数调用和 this

2. 正则匹配判断

一个字符串只由[](){}这几种构成,要求写一个函数 isMatch(str) 匹配如下格式 (1)({[())]} (2)([{({[]})})] ,结果返回 boolean

分析:要求有两个

  1. 它们是成对出现的
  2. [{(分别都是在 }])的前面 后来的代码实现:
function updateStr(str, reg) {
  let isLoop = true;
  let result = str;
  while (isLoop) {
    result = result.replace(reg, (val, str1, str2) => {
      val = val.substring(1, val.length - 1);
      return val;
    });
    if (!reg.test(result)) {
      isLoop = false;
    }
  }
  return result;
};

function isMatch(str) {
  const reg1 = /(\()[\{\}\(\[\]]*(\))/; // 每次匹配一个 (),然后去除
  const reg2 = /(\{)[\(\)\{\[\]]*(\})/;// 每次匹配一个 {},然后去除
  const reg3 = /(\[)[\[\(\)\{\}]*(\])/;// 每次匹配一个 [],然后去除
  const REGS = [reg1, reg2, reg3];
  const result = REGS.reduce((total, reg, index) => {
    return updateStr(total, reg);
  }, str);
  return !result;
}

// 测试
let strArray = ['}([(())]){', '{[{([(())])})', '{{[[{([(())])}))'];
let result = strArray.map(val => {
  return isMatch(val);
});
console.log(result);


<!--当然在 LeetCode 上也有类似的题目,通过栈的特性来解决的-->
// https://leetcode.com/problems/valid-parentheses/submissions/1
function isMatch(str) {
  let map = {
    '(': -1,
    ')': 1,
    '[': -2,
    ']': 2,
    '{': -3,
    '}': 3
  };
  let stack = [];
  for (let i =0; i < str.length; i++){
    if(map[str[i]] < 0){
      stack.push(str[i]);
    }else{
      let last = stack.pop();
      if(map[last] + map[str[i]] !==0) return false;
    }
  } 
  return stack.length <= 0;
}

3. 实现一个 LazyMan 的对象

要求如下

LazyMan('Tony');
// Hi I am Tony

LazyMan('Tony').sleep(10).eat('lunch');
// Hi I am Tony
// 等待了10秒...
// I am eating lunch

LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
// Hi I am Tony
// I am eating lunch
// 等待了10秒...
// I am eating diner

LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
// Hi I am Tony
// 等待了5秒...
// I am eating lunch
// I am eating dinner
// 等待了10秒...
// I am eating junk food

关键点:

  1. 实现一个事件队列,每次 shift() 调用一个
  2. 链式调用

答案

4. 将一维数组通过 pid 转成多维数组:

要求:

const previous = [{
    name: "1",
    id: 1,
    pid: 0
  },
  {
    name: "2",
    id: 2,
    pid: 1
  },
  {
    name: "3",
    id: 3,
    pid: 2
  }]
  
  const result = [{
    name: "1",
    id: 1,
    pid: 0,
    children:[{
         name: "2",
        id: 2,
        pid: 1
    }]
  },{
    name: "3",
    id: 3,
    pid: 2  
  }
  ]

要点:

  1. 递归
  2. 判断每一个 item 是否属于 tree 中元素
  3. 找到它的 parent,并把 item 添加到它的 children 中,返回一个新的 tree

其实就是树的不同表现形式

代码实现可以看这里 codesandbox.io/s/nw5xlozk6…

5. 模拟实现加法器

2个正整数字符串的相加,即 '1'+'19' --> '20',注意考虑超长字符串相加

思路:

  1. 超级长,不能用 parseInt,它有最大值的限制 Number.MAX_VALUE

JavaScript 类型系统——Number 数字类型

  1. 模拟实现一个十进制的加法器
  2. 可以扩展支持任意进制的运算

6. AMD,CMD,CommonJs,ES6 Module:解决原始无模块化的痛点

  • AMD:requirejs 在推广过程中对模块定义的规范化产出,提前执行,推崇依赖前置
  • CMD:seajs 在推广过程中对模块定义的规范化产出,延迟执行,推崇依赖就近
  • CommonJs:模块输出的是一个值的 copy,运行时加载,加载的是一个对象(module.exports 属性),该对象只有在脚本运行完才会生成
  • ES6 Module:模块输出的是一个值的引用,编译时输出接口,ES6 模块不是对象,它对外接口只是一种静态定义,在代码静态解析阶段就会生成。

7. HTTP 缓存有哪几种?

关键: ETag、CacheControl、Expires 参考 HTTP缓存控制小结

8. 一些 webpack -- 按需加载?构建速度?

参考

9. 翻转二叉树

JavaScript 二叉搜索树以及实现翻转二叉树

10. 自己遇到的css梳理

11. js 基础梳理 -- 冴羽大大的blog

12. web 安全

13. 静态资源放置于独立域名之下

  1. 启用新的一级域名,每次请求浏览器不会携带cookie。这对于cookie内容比较大,并且流量大的网站会省去不少宽带费用。同时这也解惑了为什么不用二三级域名。
  2. 动静分离。静态资源与动态内容分离,有利于部署于CDN,减轻web服务器压力
  3. HTTP协议对同一个域名的同时下载线程数有限制。主要是为了优化下载速度,防止同一域名下下载线程数过多,导致下载速度变慢。各个浏览器都会遵守这个规定,但是限制的数目可能不一致。基于这个原因,可将资源部署于不同的域名,以达到最大化并发下载。
  4. 静态资源独立部署,为全局产品服务。这属于业务划分的范畴了。比如taobao.com和tmll.com都会用到tbcdn.cn上的静态资源,这些资源不必从属于某个产品。
  5. 接第4点原因,有利于最大化利用客户端缓存。比如访问taobao.com,缓存了tbcdn.cn上的某个js文件,之后再访问tmll.com时,也用到此js文件,不必再从tbcdn.cn上下载,直接用客户端缓存即可。

同时,就已经减轻了每台服务器的压力,服务器越多,每个服务器压力就越小

13. react 相关

查看我的博客

总结

平时学习就要多假设一下,为什么会这样,如果换成那个(那里)又会怎么样,这两者比较起来有什么不同!总之要多总结回顾,你会有不一样的感受

还在更新当中,如果有错误,欢迎指正

参考

  1. 木易杨说的 【半月刊】前端高频面试题及答案汇总
  2. zhuanlan.zhihu.com/p/32911022