6

一次“金三银四的前端社招面经”的答案

 3 years ago
source link: https://zhuanlan.zhihu.com/p/360629666
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一次“金三银四的前端社招面经”的答案

目前前端招聘标准越来越高,上面分享的面经很具有代表性,但是只有题目没有答案,所以我就挑选了字节的1面2面,并总结了正确答案,上一篇随手答的有好些错误,一次“金三银四的前端社招面经”的解答。整理不易。

原“金三银四的前端社招面经”,里面涵盖了大量的题目。

1、TCP 和 UDP 的区别和使用场景?

区别,UDP 和 TCP 都是运输层协议,UDP 只实现了最简单的进程通信。而 TCP 实现了面向链接,传输可靠,流量控制,拥塞阻塞的功能。

使用场景,UDP:视屏直播,DNS,RIP 路由选择协议。TCP 需要上面 4 种功能的应用。

总结,推荐看这篇文章,这一篇 TCP 总结请收下,如果想深入了解,可以看《计算机网络 自顶向下方法》

2、QUIC 基于 UDP 怎么保证可靠性?

TCP 中通过三次握手,给每一份数据包添加序列,以及重试机制,保证可靠性。而 QUIC 在 UDP 的基础上,增加了一层实现 TCP 类似的功能。

总结,可参考李兵的《浏览器工作原理与实践》专栏。

3、 讲一下同源策略和跨域方案?CORS 的几个头部是什么(头部指请求头和响应头)?

同源策略:如果两个 URL 的协议、域名和端口都相同,我们就称这两个 URL 同源。浏览器默认两个相同的源可以相互访问资源和操作 DOM,这就带来了安全隐患,同源策略就是限制访问某些资源。

跨域:同源策略限制了 XMLHttpRequest、Fetch 等访问不同源的网站,这就出现了跨域问题。跨域方案:JSONP、CORS、IFrame、PostMessage,服务端层面可以用 Nginx、NodeJs 、Websocket 等。

  • Access-Control-Allow-Origin
  • Access-Control-Allow-Headers
  • Access-Control-Allow-Methods
  • Access-Control-Allow-Credentials
  • Access-Control-Allow-Headers
  • Access-Control-Allow-Methods
  • Access-Control-Allow-Origin
  • Access-Control-Expose-Headers

总结,同源策略和跨域相关的内容,看考李兵的《浏览器工作原理与实践》专栏。CORS 相关,看阮一峰的文章跨域资源共享 CORS 详解,如果没有 CORS 实践,很难答出 CORS 几个相应头和请求头的具体作用。

4、讲一下 React Fiber

下面引用来自“走进 React Fiber 的世界”这篇文章。

Fiber 可以理解为是一个执行单元,也可以理解为是一种数据结构。Fiber 可以理解为一个执行单元,每次执行完一个执行单元,React 就会检查现在还剩多少时间,如果没有时间则将控制权让出去。Fiber 还可以理解为是一种数据结构,React Fiber 就是采用链表实现的。每个 Virtual DOM 都可以表示为一个 Fiber。

总结,Fiber 是 React 实现异步更新 UI 的基础,看走进 React Fiber 的世界

5、vue 双向绑定原理?

使用 Object.defineProperty 或者 Proxy 实现数据拦截,在 getter 存储值时,在 setter 时更新值,并且更新 UI。

6、redux 和 mobx 的区别和使用场景?

  • Redux 数据存储在单一的 store,而 Mobx 将数据分散到多个 store。
  • Redux 需要手动处理数据变化后的操作(UI),而 Mobx 使用双向数据绑定,在数据变化时,直接更新 UI。
  • Redux 是函数式思想,状态不可变,每次返回新的对象,行为更可预测。而 Mobx 是面向对象的思想,状态是可变的,行为有时候不可预测。
  • Redux 异步处理需要借助中间件。而 Mobx 无需借助中间件,实现更简单。

7、typeof null?null instanceof Object?

"object",false。null instanceof Object 和 typeof null 都是 js 错误的设计。

8、typeof 可以判断哪些类型?instanceof 做了什么?

typeof 可以判断 number、boolean、symbol、string、object、undefined、function。无法判断 Date、RegExp 等复杂的对象。

这是 instanceof 的用法,但是 instanceof 的原理是什么呢?根据 ECMAScript 语言规范,我梳理了一下大概的思路,然后整理了一段代码如下 其实 instanceof 主要的实现原理就是只要右边变量的 prototype 在左边变量的原型链上即可。因此,instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,如果查找失败,则会返回 false,告诉我们左边变量并非是右边变量的实例。

function new_instance_of(leftVaule, rightVaule) {
  let rightProto = rightVaule.prototype; // 取右表达式的 prototype 值
  leftVaule = leftVaule.__proto__; // 取左表达式的__proto__值
  while (true) {
    if (leftVaule === null) {
      return false;
    }
    if (leftVaule === rightProto) {
      return true;
    }
    leftVaule = leftVaule.__proto__;
  }
}

是来自这篇掘金文章的解释。浅谈 instanceof 和 typeof 的实现原理

9、 实现一个 bind 函数

Function.prototype.myBind = function (ctx, ...rest) {
  if (typeof this !== "function") {
    throw new Error("myBind is only used to Function");
  }

  const _this = this;

  return function fn(...args) {
    // 拼接参数
    const newArgs = rest.concat(args);

    // 外部有可能 new fn();
    if (this instanceof fn) {
      return new _this(newArgs);
    }

    return _this.apply(ctx, newArgs);
  };
};

10、求数组里面最大连续项的和

[1, -2, 3, 4, -1, 5]; 输出 11,最大值是 “3,4,-1,5” 的和

function getMaxSum(arr) {
  let dp = new Array(arr.length).fill(0);

  dp[0] = arr[0];

  let maxSum = 0

  for (let i = 1; i < arr.length; i++) {

    dp[i] = Math.max(arr[i], dp[i -1] + arr[i]);

    if (dp[i] > maxSum) {
      maxSum = dp[i];
    }
  }

  return maxSum;
}

console.log(getMaxSum([1, -2, 3, 4, -1, 5]));

11、 event loop

event loop不同的宿主环境有不同的表现。

在浏览器里,event loop分为macro task和micro task。loop从一个宏任务开始,先将执行栈中的任务清空,再将微任务推到执行栈中并清空,之后检查是否存在宏任务,若存在则取出一个宏任务,执行完成检查是否有微任务,以此循环。

在node中,为了保证时间函数到点执行,每一个event loop都会先检测setTimeout是否到期。以及新增nextTrick,再当前eventLoop结束时执行的回调,而当前注册的setImmediate事件将在下次event loop执行。

两者区别,浏览器会将微任务插入到当前宏任务执行栈中,微任务和当前宏任务属于一次event loop。而node中,会先清空当前任务队列,再将微任务加入任务队列,执行时机可能是下次event loop。

  • 宏任务,有脚本执行,setTimeout等函数,用户交互等,ajax,I/O。
  • 微任务,有promise,await async,mutation,intersectionObserver,postMessage,process.nextTrick等。

浏览器中的事件循环

nodeJs中的事件循环

细节看阮一峰的文章,http://www.ruanyifeng.com/blog/2014/10/event-loop.html

1、怎么优化 h5 的加载速度?

工程和细节方向两个方向优化。 工程方向,打包内容,资源加载类型等 细节方向,熟悉浏览器特性,比如减少重绘重排。React框架,优化代码。渲染机制,懒加载(图片,资源等)。

详细到内容看这篇文章,前端性能优化总结

2、离线包怎么更新?怎么知道需要打开哪个离线包?

每次进入一个新页面,异步检查配置文件,是否需要更新。

通过版本号。

3、js bridge 通信原理?

以Android为例。

js bridge充当中间者的作用,让js和Android可以双向通信。Android将事件注入到前端上下文window中,有两种事件,一种是Android的回调事件,和React生命周期相似的事件;另一种是预留给前端主动调用Android的事件。这样前端既能主动调用Android,也能注册Android的某些事件。Android触发事件时,直接调用前端注册到JSBridge的事件。这就是双向通信了。

4、怎么实现 h5 页面秒开?

参考 前端性能优化总结

5、明明不是同一个语言,为什么 js 和 native 可以通信?

这就好像问,为什么JS能调用C++实现的原生方法。关键词,宿主环境。JS在Webview的宿主环境,而Webview在Android的宿主环境。所以通过Webview这个中间方就能通信。

6、怎么实现 js bridge 跨多个 app 共用?

封装成sdk。

7、grpc 相比 http 的优势?

grpc,google+ Remote Procedure Call。google的远程过程调用,虽然也是使用TCP/IP协议,但是框架屏蔽了底层细节。系列化方式可以是二进制,并且grpc使用的是传输层协议,更加高效。而http是WEB的通信协议,实现更加复杂,性能不如grpc。

8、rpc 的调用流程?前端怎么调用 grpc 的?

客户端发起请求,序列化数据,经过rpc,传输到指定服务端,反序列化数据,得到最终数据。

使用框架调用,Web gRPC 是 gRPC 在 Web 上的一个适配实现。

总结,rpc相关的,如果简历不写,面试官99%不会问的。

9、为什么要用 grpc?

性能更好,心智负担更小,像调本地函数一样调用。

10、服务发现为什么用 ip,而不用域名?

域名需要DNS解析。

11、怎么做 DNS 预解析?

将需要预解析的ip放到配置文件里,当应用启动时,开启一个新的线程去请求DNS服务器。

12、怎么实现移动端的布局?

可以通过百分比,rem,vw,vh等自适应方式实现布局。

13、iOS 下软键盘输入框遮挡遇到过问题么?怎么解决顶不起来的问题?

低版本IOS会出现,监听键盘弹起,自定义一个滚动事件,滚到输入框的位置。

14、实现两个大数相加

Leetcode 简单题

/**
 * @param {string} a
 * @param {string} b
 * @return {string}
 */
var addStrings = function(a, b) {
  let carry = 0;
  let index = 0;
  let result = [];
  let ra = a.split("").reverse().join("");
  let rb = b.split("").reverse().join("");

  while(index + 1 <= ra.length || index + 1 <= rb.length) {
      let _a = 0;
      let _b = 0;

      if (ra.charAt(index)) {
          _a = ra.charAt(index);
      }
      if (rb.charAt(index)) {
          _b = rb.charAt(index);
      }

      const total = Number(_a) + Number(_b) + carry;
      if (total >= 10) {
          result.push(total - 10);
          carry = 1;
      } else {
          result.push(total);
          carry = 0;
      }

      index++;
  }

  if (carry) {
      result.push(1);
  }

  return result.reverse().join('');
};

addStrings('1', '2')

15、求一个数组最大子项的和,要求这些子项在数组中的位置不是连续的。

这是LeetCode的题目,198.打家劫舍。

[1,2,3,1] 输出4,1 + 3 = 4。[2,7,9,3,1] 输出12,2 + 9 + 1 = 12

/**
 * @param {number[]} nums
 * @return {number}
 */
var rob = function(nums) {
  if (nums.length === 0) return 0;
  if (nums.length === 1) return nums[0];

  let dp = new Array(nums.length);

  dp[0] = nums[0];
  dp[1] = Math.max(nums[0], nums[1]);

  for (let i = 2; i < nums.length; i++) {
    dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);
  }

  return dp[nums.length - 1];
};

rob([2,7,9,3,1]);

16、常用的 react hooks 方法

useState、useEffect、useMemo、useCallback、useReducer、useLayoutEffect、useRef、useContext。

17、useState 怎么做缓存的?

通过一个环形链表。每一个hook都会在Fiber链表上,而useState会将同一个state都更新操作都保存到一个环形链表上,如下图。

18、react fiber 是什么?

1面回答过

19、怎么解决 useState 闭包的问题?

这个是问怎么解决useEffect闭包问题吧,传入依赖项即可。或者将state值赋值给useRef,这样每次useRef上的值都是最新的值。

20、useReducer 比 redux 好在哪里?

react内置支持。支持依赖项不更新,不触发useReducer的回调。更加轻量,无需引用框架,无需维护一个大的store树。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK