最近走访了几家互联网公司,在此整理下面试题目,希望对大家有用
面试先开始都是先做个一分半钟的自我介绍,重点突出下自己的技术栈和一两个项目,捡自己最熟悉的地方重点讲一下. 然后面试官基本都会着重问一下你参与项目里的细节.这一段大家各自发挥,没什么好说的. 聊完项目,面试官会考察应试者的前端基本功,下面是我整理的最近几家公司的面试题.
一. 前端基础题
- 有多少种方式可以让盒子垂直居中对齐
- flex-shrink:0和flex-grow:0是什么意思
- es6有哪些新特性
- 防抖和节流的区别是什么
- 不用es6 flat扁平化多维数组
- 去重一个数组,这个数组里每个元素都是对象
- 解释一下原型链
- 什么是函数式编程?js里还有什么编程范式
- 写一个函数实现instanceof
- 写一个函数实现交通灯系统
- 求和斐波那契数列,并做适当的优化
- forEach和map区别是什么
- 哪些数组方法会改变原数组
- 手写js柯里化函数
- this的指向有哪些
- 手写instance函数
- 网站性能优化有哪些?
- 强缓存和协商缓存
- http状态码有哪些?分别是什么意思
- 跨域的解决方案
- react生命周期顺序及性能优化
- react函数式组件和类组件的区别
- react父子组件通信
- setState什么时候是同步的?为什么要设计成异步
- react类组件super关键字的作用是什么? static关键字呢
- 常用的react hooks有哪些?分别代表什么意思
- 为什么不能条件使用react hooks
- react服务端渲染的原理是什么
- react map不加key会有什么影响,如果加一个随机key呢
- 什么是副作用,为什么说函数式组件没有副作用
- 为什么虚拟dom比真实dom快
- react相对于原生js的优势有哪些
- react diff和fiber算法的区别是什么
- 如何实现tooltip组件,组件式调用和方法调用有何不同,了解portal吗
- redux的数据流工作流程
- redux中间件用过哪些
- 项目中redux最佳实践有哪些
- webpack-dev-server的原理是什么
- 什么是babel-preset-env,babel-plugin-transform和babel-polyfill
- post请求和put请求的区别
- 手写nodejs如何遍历文件夹下的所有文件
- 对express中间件的理解
- 中台有哪些特点?解决了什么问题
- 一次最稳妥的git上传代码的流程是什么
- git rebase和git reset的区别是什么
- 大boss喜欢问的问题: 场景设计或给出解决方案
二. 编程问答题
1. 下面这段代码将会输出什么?简单解释一下
let n = [10, 20]
let m = n;
let x = m;
m[0] = 100;
x = [30, 40];
x[0] = 200;
m = x;
m[1] = 300;
n[2] = 400;
console.log(n, m, x)
2. 下面这段代码会有什么问题? 如果有请指出
var promise1 = function(){
return new Promise((res, rej) => {
a.b = 'c'
res()
})
.catch((err) => Promise.reject(err))
}
async function fun(){
await promise1()
console.log("1111")
... //后面还有业务逻辑
}
fun()
3. 下面这段异步代码输出结果是什么?
console.log('script start');
const dog = new Promise(function(resolve) {
console.log('dog1');
resolve();
console.log("promiseResolve")
}).then(function() {
console.log('dog2');
return "dog"
}).then(console.log("dog end"));
const cat = new Promise(function(resolve) {
console.log('cat1');
resolve();
setTimeout(() => {
console.log('setTimeout1')
})
}).then(function() {
console.log('cat2');
return "cat"
})
setTimeout(function() {
console.log('setTimeout2');
}, 0)
console.log("before promise.race")
Promise.race([dog, cat])
.then((one, two) => {
console.log("one", one)
console.log("two", two)
})
.catch(err => {
console.error('err', err);
})
console.log('script end');
4. 下面这段异步代码输出结果是什么?
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
new Promise(function(resolve) {
console.log('promise1');
resolve();
console.log("promiseResolve")
}).then(function() {
setTimeout(function() {
console.log('setTimeout1');
})
console.log('promise2');
});
}
console.log('script start');
setTimeout(function() {
console.log('setTimeout2');
}, 0)
async1();
process.nextTick(() => {
console.log("nextTick");
})
new Promise(function(resolve) {
console.log('promise3');
resolve();
setTimeout(() => {
console.log('setTimeout3')
})
}).then(function() {
console.log('promise4');
})
.then(() => console.log('promise5'))
.then(() => console.log('promise6'))
console.log('script end');
5. 下面这段代码输出结果是什么?假如最后输出的结果不是我们想要的,怎么改
const arr = [1,2,3,4,5,6]
arr.forEach(async (item) => {
await sleep(item)
console.log('after', item)
})
function sleep(item){
return new Promise(res => {
setTimeout(() => {
res(console.log('before', item))
}, 2000)
})
}
6. 下面这段异步代码输出结果是什么?
const queue = [1,2,3,4]
function func(){
return new Promise(async res => {
await sleep()
res(queue[0])
if(queue.shift()){
return func()
}
})
}
function sleep(){
return new Promise(res => {
setTimeout(() => res(), 2000)
})
}
func()
.then((result) => {
console.log('result', result)
})
6. 下面这段异步代码输出结果是什么?
function a(){
return new Promise(res => {
console.log(3)
setTimeout(() => {
console.log(4)
res()
}, 2000)
})
}
function b(){
return new Promise(async res => {
console.log(1)
res()
console.log(2)
await a()
console.log(5)
})
}
b().then(() => {
console.log(6)
})
7. 下面这段异步代码输出结果是什么?
new Promise(res => {
setTimeout(() => {
console.log(1)
res()
})
console.log(2)
})
console.log(3)
二. 大厂笔试题
字节跳动
1. 有N个请求,每次发送一个,如果有一个失败了,就不再执行后面的请求并返回直到上一个请求的所有结果,否则返回所有结果
// 我这里用异步宏任务模拟请求
const result = []
const arr = [1,2,3,4,5,6,7]
function call(data){
return new Promise((res, rej) => {
setTimeout(() => {
if(data === "5"){
rej(data)
} else {
res(data)
}
}, 1000)
})
}
function foo(){
return call(arr.splice(0, 1).join(""))
.then((response) => {
console.log("response", response)
result.push(response)
if(arr.length){
return foo()
} else {
console.log("result", result)
return result
}
})
.catch(err => {
console.log("result", result)
return result
})
}
foo()
2. 写一段柯里化函数实现下面的功能
function add(a, b, c){
return a+b+c
}
curry(add)(1)(2)(3)
curry(add, 1)(2)(3)
curry(add, 1, 2)(3)
curry(add, 1, 2, 3)
// 答案
function curry(func, ...args1){
let arr = [...args1]
if(func.length <= args1.length){
return func.apply(this, args1)
} else {
const foo = function(...args2){
arr = [...arr, ...args2]
if(func.length <= arr.length){
return func.apply(this, arr)
} else {
return foo
}
}
return foo
}
}
console.log(curry(add, 1, 2, 3))
头条面试官还出了一道关于数据结构的算法题,我对数据结构不是很了解,心想如果下次再遇到数据结构的算法题,打算直接说不会
阿里巴巴
1. 请使用 html + css 实现以下效果,且不管浏览器如果缩放,始终保持下图在浏览器水平和垂直方向的中间(十字架需css绘制)
<html lang="en">
<head>
<meta charset="utf-8" />
<title>align</title>
<style type="text/css">
.container{
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
height: 100%;
width: 100%;
background-color: #ccc;
}
.top{
width: 30px;
height: 50px;
background-color: #fff;
border: 2px solid blue;
border-bottom: 0;
}
.middle{
display: flex;
background-color: #fff;
}
.left, .right{
width: 50px;
height: 30px;
background-color: #fff;
}
.left{
border: 2px solid blue;
border-right: 0;
margin-right: 15px;
}
.right{
border: 2px solid blue;
border-left: 0;
margin-left: 15px;
}
.bottom{
width: 30px;
height: 50px;
background-color: #fff;
border: 2px solid blue;
border-top: 0;
}
</style>
</head>
<body>
<div class="container">
<div class="top"></div>
<div class="middle">
<div class="left"></div>
<div class="right"></div>
</div>
<div class="bottom"></div>
</div>
</body>
</html>
2. 实现以下函数 /**
- 说明:实现一个方法,用于比较两个版本号(version1、version2)
-
如果version1 > version2,返回1;如果version1 < version2,返回-1,其他情况返回0
-
版本号规则`x.y.z`,xyz均为大于等于0的整数,至少有x位
- 示例:
- compareVersion('0.1', '1.1.1'); // 返回-1
- compareVersion('13.37', '1.2 '); // 返回1
- compareVersion('1.1', '1.1.0'); // 返回0 */
// 答案
function compareVersion(version1, version2){
const version1Arr = version1.split(".")
const version2Arr = version2.split(".")
const length = Math.max(version1Arr.length, version2Arr.length)
for(let i=0; i < length; i++){
if(i<(length-1)){
if(Number(version1Arr[i]) > Number(version2Arr[i])){
return 1
} else if(Number(version1Arr[i]) < Number(version2Arr[i])){
return -1
}
} else {
const firstThird = version1Arr[length-1] || 0
const SecondThird = version2Arr[length-1] || 0
if(firstThird > SecondThird){
return 1
} else if(firstThird < SecondThird){
return -1
} else {
return 0
}
}
}
}
3. 有一个对象X,内容如下,请写程序找出所有d的值
const X = {
y: {
c: {
d: 1
}
},
z: {
e: {
d: 2
}
},
q: {
f: {
d: 3
}
},
o: {
m: {
g: {
h: {
d: 4
}
}
}
}
}
// 答案
const resultArr = []
function lookup(obj){
for(let i in obj){
if(Object.prototype.toString.call(obj[i]) === '[object Object]'){
lookup(obj[i])
} else if(i === "d"){
resultArr.push(obj.d)
}
}
}
lookup(X)
console.log("resultArr", resultArr)
4. 实现以下功能,已知有 N 个 url,每次最多可并行请求 M,尽快完成对 N 个 url 的请求并保存所有返回结果到数组中。(每次发M个请求,每完成一个请求就发送一个剩下的请求)
const urls = ["1", '2', '3', '4', '5', '6', '7']
const results = []
const promises = []
function getData(url) {
return fetch(url)
.then((response) => {
results.push(response)
if(urls.length) {
return getData(urls.splice(0, 1).join(""))
}
})
}
urls.splice(0, M).forEach(item => {
promises.push(getData(item))
})
Promise.all(promises)
.then(() => {
console.log('results', results)
})