字节前端三面凉经

一面:

JS 基础数据类型有哪些?

Number、String、BigInt、Boolean 、Undefined、Null、Symbol

补充复杂类型:Object

this的指向
function a(){console.log(this)} a()  // Window
var b = { a: a} b.a() // b
new A()
  1. 在内存中创建一个新的空对象
  2. 让this指向这个空对象
  3. 执行构造函数里面的代码(给这个新对象添加属性和方法)
  4. 返回这个新对象
实现下二叉树的深度遍历,筛选不重复节点的名字

深度优先

function mapDom(tree) {
  let visited = [];

  let traverse = function (node) {
    if (node.left) traverse(node.left);
    if (!visited.contains(node)) {
      visited.push(node);
    }
    if (node.right) traverse(node.right);
  };
  traverse(tree.root);
  return visited;
}

广度优先

function mapDom(tree) {
  let visited = [];
  let queue = [];
  queue.push(tree.root);

  while (queue.length) {
    let current = queue.shift();
    if (!visited.contains(current)) {
      visited.push(current);
    }
    if (current.left) {
      queue.push(current.left);
    }
    if (current.right) {
      queue.push(current.right);
    }
  }
  return visited;
}
flex是哪三个属性简写

flex-grow 定义项目的放大比例,默认为0(即使有空间也不放大)

flex-shrink 定义项目的缩小比例,默认为1(空间不足时自动缩小)

flex-basis 定义项目初始宽度,默认为auto(项目本来大小)

用css实现朝上的红色三角
div {
  width: 0;
  height: 0;
  border: 2em solid transparent;
  border-bottom-color: red;
}
cdn如何工作

CDN的全称是Content Delivery Network,即内容分发网络。CDN是构建在网络之上的内容分发网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。

选择器的权重

!important 最高

内联样式 权值 1000

#id 权值 100

类、伪类选择器 权值 10

元素、伪元素选择器 权值为 1

通配符(*)、子选择器(>)、相邻选择器 权值 0

继承样式没有权值

11个类选择器虽然权值之和大于一个id选择器,但是浏览器还是优先解析id选择器

设置宽高为100px的盒子,包括哪些内容

box-sizing 有三个属性

content-box(默认盒子),height和width设置的是内容的宽高,实际盒子宽度=左右border+左右padding+width

border-box,height和width包括了的内容、内边距和边框,实际盒子宽度=width

浏览器兼容性

使用厂商前缀

can i use 查看属性兼容性

如何打破Promise链
fetch("https://v1.hitokoto.co")
  .then((res) => res.json())
  .then((data) => console.log(data))
  .catch((err) => console.log("错误"))
  .then((res) => console.log("错误被捕获后, .then 执行了"))
  .catch((err) => console.log("错误被捕获后, .catch 不执行"));

上面代码输出如下

错误
错误被捕获后, .then 执行了

感觉没有答案...

position:fixed 如何不相对于浏览器定位

给其祖先结点加上transform为非none。

cache-control

响应头

expires 过期时间(时间戳),在这个时间内使用强缓存 单位:毫秒

cache-control 设置浏览器多长时间内再次请求会命中强缓存 单位:秒

-no-cache 不使用本地缓存

-no-store 禁止浏览器缓存

etag 第一次请求时,响应头包含该字段,第二次请求时,请求头的 If-None-Match 就是etag值,服务端拿到etag,对比资源是否发生变化,若没有变化,返回304

last-modified 第一次请求URL时,响应头包含该字段,标志文件在服务器最后被修改时间

If-Modified-Since 第二次请求URL时,请求头包含该字段,向服务器询问该文件是否修改,没有修改返回304,直接从缓存读取。

expires 和cache-control 区别:

expires 有一个缺陷,即要求服务端和客户端时间同步,如果不同步,假如服务器慢了,传给客户端的时间可能一直过期了。

Vue nextTick 和nodejs nextTick

更改dom元素内部文本后,需要dom更新后才能获得更改后的内容。this.$nextTick()可以将回调延迟到下次 DOM 更新循环之后执行。

Nodejs事件循环

NodeJS将异步任务交给内核完成,在任务完成时,内核通知NodeJS将回调函数添加到轮询队列中等待时机执行。

垂直居中
position:absolute不设置top、left会怎样

保持正常文档流位置,但不占用空间

get 和 post 的区别
  • GET 将数据附在URL之后,POST则是放在HTTP包中
  • GET长度受到url长度限制,POST没有大小限制
  • POST安全性比GET高
  • GET只允许ASCII,POST没有限制
  • GET后退刷新无害,POST重新提交表单
fetch发送2次请求的原因

fetch发送post请求的时候,总是发送2次,第一次状态码是204,第二次才成功?原因很简单,因为你用fetch发送post请求的时候,fetch 第一次发送了一个Options请求,询问服务器是否支持修改的请求头,如果服务器支持,则在第二次中发送真正的请求。

js垃圾回收机制

一般来说,没有被引用的对象就是垃圾,就是要被清除,有个例外如果有几个对象引用形成一个环,互相引用,但根访问不到他们,这几个对象也是垃圾。

如何检查垃圾

使用标记-清除算法

二面

进程通信方式
  • 管道通信
  • 信号及信号量通信
  • 共享内存
  • socket

补充Node进程通信方式

  • 通过stdin/stdout传递

  • Node原生IPC支持

  • 通过sockets

  • 借助message queue

如何防止盗链

判断引用地址

请求头中包含Referer字段,如果这个字段的值是自己的域名,则响应请求,否则返回错误信息

图片格式有哪些?webp是什么

bmp、jpg、png、gif、svg、webp

webp 是一种同时提供了有损压缩与无损压缩(可逆压缩)的图片文件格式。webp可以在压缩的同时又不影响图片格式兼容与实际清晰度,进而让整体网页下载速度加快。

git命令有哪些?git tag是什么

git tag 基于最新提交创建标签

如何撤销已提交的代码

方法一

远程回退

git push origin :

commit_id可以通过git log查看,或者在直接从github网站上复制

本地回退

git reset --hard 

方法二

git reset --hard 
git push origin +

注意版本号前面的+ ,它类似于--force,但略有不同,省略后提交会失败

Nginx有哪些配置项

listen、server_name、location、root等

使用shell读取指定行或列
sed -n '5,10p' /etc/passwd;
如果加载大量图片需要怎么做

懒加载、雪碧图

雪碧图怎么实现

将小图标和背景图像合并到一张图片上,然后利用css的背景定位来显示需要显示的图片部分

正向代理和反向代理

正向代理:客户端将请求发送给代理服务器,再由代理服务器进行发送请求,获得的响应也通过这种方式。

反向代理:客户端发送请求后,请求被转发到服务端的某个端口

大数相加
function bigNumberSum(a, b) {
  // 123456789
  // 000009876

  // padding
  let cur = 0;
  while (cur < a.length || cur < b.length) {
    if (!a[cur]) {
      a = "0" + a;
    } else if (!b[cur]) {
      b = "0" + b;
    }
    cur++;
  }

  let carried = 0;
  const res = [];

  for (let i = a.length - 1; i > -1; i--) {
    const sum = carried + parseInt(a[i]) + parseInt(b[i]);
    if (sum > 9) {
      carried = 1;
    } else {
      carried = 0;
    }
    res[i] = sum % 10;
  }
  if (carried === 1) {
    res.unshift(1);
  }

  return res.join("");
}
console.log(bigNumberSum("1122", "3344"));
实现一个时钟动画

html

css

.clock-wrapper {
  box-sizing: border-box;
  height: 200px;
  width: 200px;
  padding: 2%;
  background: #333;
  border-radius: 50%;
}
.clock {
  height: 100%;
  width: 100%;
  position: relative;
}
.clock div {
  position: absolute;
  height: 2px;
  width: 50%;
  background: white;
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  transform-origin: 100%;
  animation: rotate 60s infinite linear;
}
@keyframes rotate {
  0% {
    transform: translateY(-50%) rotate(0);
  }
  100% {
    transform: translateY(-50%) rotate(360deg);
  }
}

UY081S.png

三面

前几面的感受
你觉得难的问题
ajax请求
function ajax(url) {
  const xhr = new XMLHttpRequest();
  xhr.open("GET", url);
  xhr.send();
  xhr.onload = function () {
    if (this.status === 200) {
      console.log(this.response);
    }
  };
}
发送json数据
function ajax(url, data) {
  const xhr = new XMLHttpRequest();
  xhr.open("POST", url, true);
  xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
  xhr.send(JSON.stringify(data));
  xhr.onload = function () {
    if (this.status === 201) {
      console.log(this.response);
    }
  };
}
大数相乘
let multiply = function (num1, num2) {
  //判断输入是不是数字
  if (isNaN(num1) || isNaN(num2)) return "";
  let len1 = num1.length,
    len2 = num2.length;
  let ans = [];

  //这里倒过来遍历很妙,不需要处理进位了
  for (let i = len1 - 1; i <= 0; i--) {
    for (let j = len2 - 1; j >= 0; j--) {
      let index1 = i + j,
        index2 = i + j + 1;
      let mul = num1[i] * num2[j] + (ans[index2] || 0);
      ans[index1] = Math.floor(mul / 10) + (ans[index1] || 0);
      ans[index2] = mul % 10;
    }
  }

  //去掉前置0
  let result = ans.join("").replace(/^0+/, "");

  //不要转成数字判断,否则可能会超精度!
  return !result ? "0" : result;
};
js中多大的数称为大数

超出Number.MAX_VALUE(1.7976931348623157e+308)

http响应码

参考https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status

对ajax请求进行promise封装
function ajax(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.send();
    xhr.onreadystatechange = function () {
      if (this.readyState == 4) {
        if (this.status == 200) {
          try {
            let response = JSON.parse(this.responseText);
            resolve(response);
          } catch (e) {
            reject(e);
          }
        } else {
          reject(new Error(this.statusText));
        }
      }
    };
  });
}
你有什么问题

可以从岗位工作内容、对产品看法、以及某个技术问题回答

面试感受

面试前准备
心理准备

面试官大部分年纪都不大,没有那种咄咄逼人的感觉,大多数都以平等的姿态和你沟通,所以不必要太紧张。

知识储备
  • 面经
  • 算法题
  • 前端基础知识(JS、CSS、Vue/React)
  • 项目经历

以上内容除了最后一个都可以在牛客网找到

面试问题

如果是应届生,字节面试会以考察计算机基础(计算机网络、操作系统、数据结构)为主,应该好好复习这一块知识,笔者以为只会考察网络,结果二面时问了许多操作系统,就没答上来,本来以为二面就凉了,后来还是收到三面通知,这是让我比较意外的。字节大多数技术岗位都重视算法,前端面试算法虽然不会太难,但会考察各类经典题型的变种,所以光靠熟悉各种经典题型是不够的,还要掌握一类题的解题思路。

最后想说的

每一轮面试完后,如果几个小时内没有人联系你,最好打电话问一下面试结果,即使没有出结果,也可以加深面试官对你的印象,让人觉得你很重视这份工作。字节面试结果一般出的比较快,如果能力强的,面试完当天oc的也有,笔者属于比较菜的,三轮面试完后了无音讯,七天后成了凉面。

你可能感兴趣的:(字节前端三面凉经)