第一次大公司面试的面经
此次面试说来也有点匆忙, 本没想过自己会那么快就想去面试大公司, 并且把自己第一次面大公司的各种不足展现得一览无余. 当时 11 月 20 号左右身边一位朋友给了一位人超 nice 的师兄的内推, 并且鼓励我去投简历. 最终战胜了自己的胆怯, 投了一份简历给内推的师兄. 一两天后 hr 就打电话安排面试了.
没想到面试是要连续着面的, 当时面花了一个多小时过了一面, 再花一个小时面二面, 最终也止于二面. 接下来就是本文的主题了. 我把当时面试官通过牛课网在线面试平台中写给我做的题记录了下来, 其实从面试前就打算把面试学到的东西积累下来. 接下来就进入本文的主题了, 我也尽量把每一道题都写上我的解题思路, 希望能得到大家更多更好的意见.
一面
一, 请问运行这段代码会输出什么.
- let obj = {
- name: 'bytedance',
- getName() {
- return this.name
- }
- }
- let fb = obj.getName;
- fb();
A: 我当时好像是答 undefined. 但我知道这不会是输出 "bytedance", 因为当 obj.getName 赋给 fb 的时候它的 this 也改变了, 具体可以看我之前总结了一篇 JavaScript 中的 this 的文章. 然后我后来我在浏览器中运行了一下代码发现是输出 "" ...
二, 设计一个简单的任务队列, 要求分别在 1,3,4 秒后打印出 "1","2","3"
- new Quene()
- .task(1000, () => {
- console.log(1)
- })
- .task(2000, () => {
- console.log(2)
- })
- .task(1000, () => {
- console.log(3)
- })
- .start()
- function Quene() { ... }
A: 讲真, 看到这道题的时候我第一时间感到自己完了, 虽然也只写了一点, 没有全部做出来, 然后就跳过这道题了. 面试完就努力着把这道题写出来
- function Quene() {
- this.task = (time, callback) => {
- setTimeout(callback, time);
- // console.log(this)
- return this;
- };
- this.start = () => {
- return this;
- };
- }
虽然这样即使最后面不用写. start() 也能打印出来... 希望能得到指点 Q_Q
三, 给定一个升序整数数组 [0,1,2,4,5,7,13,15,16], 找出其中连续出现的数字区间如下:
- ["0->2","4->5","7","13","15->16"]
- A:
- function Arr(arr) {
- var len = arr.length,
- j,
- newArr = [],
- str = '';
- for (var i = 0; i <len; i++) {
- j = i;
- if (arr[i] + 1 === arr[j + 1]) {
- while (arr[j] + 1 === arr[j + 1]) {
- str = '->' + arr[j + 1];
- j++;
- }
- str = arr[i] + str;
- newArr.push(str)
- i = j
- } else {
- newArr.push(arr[i].toString())
- }
- }
- return newArr;
- }
还算比较简单的算法题吧, 还好当时做出来了, 不然可能就止步于此.. 也希望大家能谈点自己对这道题的解法
四, TCP 协议建立连接的过程, 进程间通信的方式有哪些
TCP 建立连接的过程即为三次握手, 三次握手可以参考我之前发的文章, 网上也有很多资料, 这里就不细讲.
至于进程间的通信方式, 当时没能打出来 (这就涉及到我的知识盲区了 [哭丧脸] ), 后来网上查了一下, 有:
管道 pipe: 管道是一种半双工的通信方式, 数据只能单向流动, 而且只能在具有亲缘关系的进程间使用. 进程的亲缘关系通常是指父子进程关系.
命名管道 FIFO: 有名管道也是半双工的通信方式, 但是它允许无亲缘关系进程间的通信.
消息队列 MessageQueue: 消息队列是由消息的链表, 存放在内核中并由消息队列标识符标识. 消息队列克服了信号传递信息少, 管道只能承载无格式字节流以及缓冲区大小受限等缺点.
共享存储 SharedMemory: 共享内存就是映射一段能被其他进程所访问的内存, 这段共享内存由一个进程创建, 但多个进程都可以访问. 共享内存是最快的 IPC 方式, 它是针对其他进程间通信方式运行效率低而专门设计的. 它往往与其他通信机制, 如信号两, 配合使用, 来实现进程间的同步和通信.
信号量 Semaphore: 信号量是一个计数器, 可以用来控制多个进程对共享资源的访问. 它常作为一种锁机制, 防止某进程正在访问共享资源时, 其他进程也访问该资源. 因此, 主要作为进程间以及同一进程内不同线程之间的同步手段.
套接字 Socket: 套解口也是一种进程间通信机制, 与其他通信机制不同的是, 它可用于不同及其间的进程通信.
信号 ( sinal ) : 信号是一种比较复杂的通信方式, 用于通知接收进程某个事件已经发生.
这里有个题外话, 如果面试官问浏览器窗口间的通信, 那么有以下几种:
- 1.localStore
- localStorage.setItem("name", name);
- 2.cookie + setInterval
在页面 A 设置一个使用 setInterval 定时器不断刷新, 检查 cookie 的值是否发生变化, 如果变化就进行刷新的操作.
由于 cookie 是在同域可读的, 所以在页面 B 改变 cookie 的值, 页面 A 是可以拿到的.
五, 用纯 CSS 创建一个三角形的原理是什么? 如何实现?
A: 用 CSS 创建一个三角形的原理是分别设置上下左右的 border 属性, 中间内容为 0 面积. 实现:
- #box {
- width: 0;
- height: 0;
- border-left: 50px transparent solid;
- border-right: 50px transparent solid;
- border-top: 50px transparent solid;
- border-bottom: 50px black solid;
- }
六, 0.1 + 0.2> 0.3 返回什么?
A:true. 分别转成 2 进制.
七, 类数组对象是什么?
刚开始还对这个类数组感到懵逼, 后来面试官一提醒函数的参数马上领悟到就是伪数组.
A: 只包含使用从零开始, 且自然递增的整数做键名, 并且定义了 length 表示元素个数的对象.
function 内部的 arguments 对象就是一个类数组对象
DOM 方法 document.getElementsByTagName()... 也是返回一个类数组对象
八, 什么是同源策略, 为什么会有这种策略
源包括三个部分: 协议, 域名, 端口 (HTTP 协议的默认端口是 80). 如果其中有任何一个部分不同, 则源不同. 即为跨域.
限制一个源加载的文档或脚本与来自另一个源的资源进行交互. 这是一个用于隔离潜在恶意文件的关键的安全机制.(来自 MDN 的解释)
九, 什么 CORS
A: 受同源策略的限制, 支持跨域; 一种新的通信协议标准. 可以理解成同时支持同源和跨域的 Ajax.
MDN 解释: 跨域资源共享 (CORS) 是一种机制, 它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的 web 应用被准许访问来自不同源服务器上的指定的资源. 当一个资源从与该资源本身所在的服务器不同的域, 协议或端口请求一个资源时, 资源会发起一个跨域 HTTP 请求.
十, 什么是 OPTIONS 请求
A:OPTIONS 请求是 HTTP 请求的一种方法, 返回服务器针对特定资源所支持的 HTTP 请求方法, 也可以利用向 Web 服务器发送'*'的请求来测试服务器的功能性
然后一面就这样结束了, 面试官也直接跟我说我通过了一面, 我也问了一些问题后就结束面试了. 我赶紧把平台上的面试记录记下来, 过了几分钟, 当我还沉浸在通过一面的愉悦和全身心已经放松了的情况下, 发现手机有几个未接电话, 然后又再打进了一个, 接通电话后对方是头条 hr 小姐姐, 问我说现在可以二面了, 二面的面试官已经在平台上等着了... 好吧, 这太突然了, 我马上赶赴战场.
<hr/>
二面
一, fetch
A:Fetch API 提供了一个获取资源的接口 (包括跨域请求). 无论请求成功与否, 它都返回一个 Promise 对象;
二, 用 Promise 实现延迟 3 秒后输出 delay(3000).then(f,e)
- A:
- function delay(timer) {
- return new Promise(function(resolve, reject) {
- setTimeout(function() {
- resolve();
- }, timer)
- })
- }
三, XSS/CSRF
XSS: 跨站脚本 (Cross-site scripting)
通过提交或其他方式例如发布评论, 其中含有 html 或 JavaScript 的代码, 如果服务器没有过滤掉这些脚本, 这些脚本在一些情况下就可能会运行.
避免 XSS 的方法之一就是过滤用户提供的内容, 如 <,>,script;
cookie 设置 HttpOnly 属性
CSRF: 跨站请求伪造 (Cross-site request forgery)
是一种劫持受信任用户向服务器发送非预期请求的攻击方式, 即在用户登陆某个平台化拿到用户的登陆凭证后发送伪造请求
防范 CSRF 的方法之一就是通过验证码
Referer Check, 根据 HTTP 协议, 在 HTTP 头中有一个字段叫 Referer, 它记录了该 HTTP 请求的来源地址. 通过 Referer Check, 可以检查请求是否来自合法的 "源".
添加 token 验证, 可以在 HTTP 请求中以参数的形式加入一个随机产生的 token, 该 token 不存在与 cookie 中, 并在服务器端建立一个拦截器来验证这个 token, 如果请求中没有 token 或者 token 内容不正确, 则认为可能是 CSRF 攻击而拒绝该请求.
四, 图片懒加载原理 (lazy image)
A: 给每张图片添加一个 data-xxx 的属性用于存放图片的 src, 检测到图片进入视野中的时候把 data-xxx 的属性赋给 src
如何检测图片进入视野:
a.document.documentElement.clientHeight 获取屏幕可视窗口高度
b.element.offsetTop 获取元素相对于文档顶部的距离
c.document.documentElement.scrollTop 获取滚动被卷去的高度
如果 b-c<a 成立则元素进入可视区域
这里我还提到一个函数节流提高性能:
- var canRun = true;
- document.getElementById("throttle").onscroll = function(){
- if(!canRun){
- // 判断是否已空闲, 如果在执行中, 则直接 return
- return;
- }
- canRun = false;
- setTimeout(function(){
- // 这里加载图片
- console.log("函数节流");
- canRun = true;
- }, 500);
- };
五, 上传图片
表单上传
(1). 提供 form 表单, method 必须是 post.
(2). form 表单的 enctype 必须是 multipart/form-data.
Ajax 上传
Ajax 和 FormData 可实现页面无刷新的文件上传效果
六, 将一些 ES6 的新特性
可以参考之前写的文章, 不过当时到了后面真是精疲力竭, 连 let 和 const 都没有说出来...
七, jsbridge
问到这个概念的时候我不清楚, 记得当前前一两天掘金刚发一篇相关的文章给我, 然而当时没去看..
JSBridge 简单来讲, 主要是 给 JavaScript 提供调用 Native 功能的接口, 让混合开发中的 "前端部分" 可以方便地使用地址位置, 摄像头甚至支付等 Native 功能. 是 Native 和非 Native 之间的桥梁, 它的核心是构建 Native 和非 Native 间消息通信的通道, 而且是双向通信的通道.
二面其中也包含一些 IQ 题, 还有后面问我如果实习能实习多久我说 3 个月. 之后第二天就收到把我简历 "丢进" 公司人才库的邮件了.
当然这只是其中一部分题目, 一些面试官口头问的我当时面试完真是超级累也忘了记录下来. 总之, 感觉头条还是会比较重视算法和新技术.
希望这一两个月能够好好把握, 春招再战!!
来源: https://segmentfault.com/a/1190000018025701