一面:
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()
- 在内存中创建一个新的空对象
- 让this指向这个空对象
- 执行构造函数里面的代码(给这个新对象添加属性和方法)
- 返回这个新对象
实现下二叉树的深度遍历,筛选不重复节点的名字
深度优先
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 <tagname>
基于最新提交创建标签
如何撤销已提交的代码
方法一
远程回退
git push origin <commit_id>:<branch>
commit_id
可以通过git log
查看,或者在直接从github网站上复制
本地回退
git reset --hard <commit_id>
方法二
git reset --hard <commit_id>
git push origin +<branch>
注意版本号前面的
+
,它类似于--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
<div class="clock-wrapper">
<div class="clock">
<div class="hour"></div>
</div>
</div>
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);
}
}
三面
前几面的感受
你觉得难的问题
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的也有,笔者属于比较菜的,三轮面试完后了无音讯,七天后成了凉面。