小米前端开发一面

25,118 阅读9分钟

前言

秋招已经差不多开始了,小编我呀前段时间也是陆陆续续的面了许多家的中小公司,投了许多简历今天也是终于约到了一份大厂小米的前端实习面试,这不刚面完就来记录下这次的的面试经历。

一、自我介绍

面试刚开始也是和正常的公司一样,面试官让你简单的做个自我介绍,于是我就框框框的对着面试官一顿输出,相信正在秋招的友友们也已经说过n遍了,已经烂熟于心了吧。这里我就不在叙述了。

二、手写promise

自我介绍完后,面试官也是点头回应了一句后就直接来上一句,那你先手写一下promise吧,果然大厂的面试就是不一样,上来就要我手写,用promise实现让b函数在异步代码a函数执行1000毫秒后执行,我以为他是要我实现一个定时器用promise写,于是我就框框框就是一顿敲

function a() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("a is ok");
      resolve(1)
      //reject(1)
    }, 1000);
  });
}
function b() {
  console.log("b is ok");
}
a().then(
  (res) => {
    //console.log(res, "+++");
    b();
  },
  (err) => {
    console.log(err, "---");
  }
);

我敲完之后他看了看说嗯,还可以,结果来一句,那你直到promise的源码吗,可以手写一下吗?

我:......顿了半天,跟他说嗯,了解过,我试试写写,写了一会也是直接就把promise的源码写了一下,后面的.then的源码倒是没有继续写下去了,面试官看完写完promise的源码后也是没有继续为难我,就说好了,差不多可以,就这样吧,就继续问我下一题了.

关于promise和.then的源码大家可以看看我的这篇文章

面试官:手写下promise和then的源码前言 promise在我们学习javaScript的过程中也是一个非常重要的 - 掘金 (juejin.cn)

三、手画一个三角形

这里面试官是让我用css实现一个三角形,可能没有了解看过这种的题目的小伙伴会无从下手,但是其实用css是可以实现一些简单的像圆和三角形这些几何图形的,实现三角形的方法有很多种,我这里想到的是通过边框来实现三角形。

.box{
			border-left:50px solid transparent;
			border-right:50px solid transparent;
			border-bottom:50px solid #333;
			width:0;
			height:0;
	}

这样一个三角形也就画出来了。

三角形可以用border画出来,首先一个有四个border的div应该是正方形,设置宽高和四个边框如border-left:50px solid #000;

	<style>
		.box{
			border-left:50px solid #000;
			border-right:50px solid #333;
			border-top:50px solid #666;
			border-bottom:50px solid #999;
			width:100px;
			height:100px;
			background-color: #ccc;
		}
		</style>
	</head>
	<body>
		<div class="box"></div>
	</body>

然后我们把它的高度和宽度去掉,剩下四个border.如下图:

	.box{
			border-left:50px solid #000;
			border-right:50px solid #333;
			border-top:50px solid #666;
			border-bottom:50px solid #999;
			width:0;
			height:0;
	}

image-20240823211105230

再把border-top去掉,这样就把上面的区域给裁掉了。

	.box{
			border-left:50px solid #000;
			border-right:50px solid #333;
			border-bottom:50px solid #999;
			width:0;
			height:0;
		}

image-20240823211204193

接下来,再让左右两边的border透明,就得到了三角形

	.box{
			border-left:50px solid transparent;
			border-right:50px solid transparent;
			border-bottom:50px solid #333;
			width:0;
			height:0;
	}

image-20240823211244107

当然,也还有其他方式也可以实现画一个三角形,像还可以通过使用clip-path,还有使用:before伪元素和使用::after伪元素等,方法还有很多,大家可以自行去了解一下。

四、事件循环机制题目

接下来面试官就给了我一道关于判断事件循环机制的题目让我做,小编对这个也是心有成竹,也是把它做出来了,事件循环机制在面试中是一个非常被容易问到的一个知识点,这里我就不具体跟大家叙述了,大家有不懂的可以看看我之前写的这篇文章。

三道面试题带你了解js事件循环机制前言: 什么是js的事件循环机制呢?JavaScript的事件循环机制(Event L - 掘金 (juejin.cn)

五、手写实现三种水平垂直居中的方法

然后面试官也是问了我一些css布局相关的问题,让我手写出三种实现水平居中的方法。小编我也是立马就写了三种出来

方法一:弹性flex

<style>
        .box {
            width: 500px;
            height: 500px;
            background-color: rgb(28, 101, 164);
            display: flex;
            justify-content: center;
            align-items: center;
        }
        .wrap {
		   width: 200px;
            height: 200px;
            background-color: green;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="wrap"></div>
    </div>
</body>

justify-content: center是主轴居中,align-item: center是交叉轴居中

方法二:定位absolute+translate

给top和left分别一个50%,然后自身再top和left负50%

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box {
            width: 500px;
            height: 500px;
            background-color: rgb(28, 101, 164);
            position: relative;
        }
        .wrap {
            width: 200px;
            height: 200px;
            background-color: green;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            /* margin-top: -100px; */
            /* margin-left: -100px; */
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="wrap"></div>
    </div>
</body>
</html><!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box {
            width: 500px;
            height: 500px;
            background-color: rgb(28, 101, 164);
            position: relative;
        }
        .wrap {
            width: 200px;
            height: 200px;
            background-color: green;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            /* margin-top: -100px; */
            /* margin-left: -100px; */
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="wrap"></div>
    </div>
</body>
</html>

如果已知宽高的时候也可以不用translate,直接写成margin-left:-100px和margin-top:-100px.

方法三:定位+margin auto

<style>
    .father{
        width:500px;
        height:300px;
        border:1px solid #0a3b98;
        position: relative;
    }
    .son{
        width:100px;
        height:40px;
        background: #f0a238;
        position: absolute;
        top:0;
        left:0;
        right:0;
        bottom:0;
        margin:auto;
    }
 </style>
 <div class="father">
    <div class="son"></div>
 </div

父级设置为相对定位,子级绝对定位,并且四个定位属性的值都设置了0,那么这时候如果子级没有设置宽高,则会被拉开到和父级一样宽高

这里子元素设置了宽高,所以宽高会按照我们的设置来显示,但是实际上子级的虚拟占位已经撑满了整个父级,这时候再给它一个margin:auto它就可以上下左右都居中了。

六、问了一些简单的js和vue的基础题目

然后就是接着聊了聊一些js和vue的一些知识,具体问的啥我可能也不太记得了,但是都是挺基础的。

七、算法题

最后就是算法题了,我就知道大厂的面试一定少不了算法,果然,问了我一道关于合并重叠的子数组的问题,题目大概意思如下:

合并重叠的子数组,有一个数组包含多个子数组,每个子数组都由不同的时间段[starti,endi]组成,要求合并所有重叠的时间段,返回一个新的二维数组。

输入intervals:一个二维数组,其中每个元素也是一个数组 [start, end] 表示一个时间段,startend 均为整数,且满足 start <= end

例输入: [[1, 3], [2, 6], [8, 10], [15, 18]];

输出:返回一个二维数组,包含合并后的所有不重叠的时间段。

输出:[[1, 6], [8, 10], [15, 18]]

思路:

首先咱们就是要先对输入的所有的子数组的起始时间段进行一个从小到大的排序,这样的话咱们后续就可以更好的检测重叠区间,然后需要创建一个空数组用于存放合并后的区间,接下来就是要遍历排序后的区间列表intervals,对于每个区间 interval,我们检查它是否与 merged 数组中最后一个已经合并的区间重叠。然后对每个区间interval,检查是否重叠,如果没有重叠,就push到新创建的数组merged中,如果有重叠,则更新 merged 数组中最后一个区间的结束时间,使其成为这两个区间结束时间中的最大值。最后返回这个merged数组就行了。

代码实现:

function mergeOverlappingIntervals(intervals) {
    // 对区间按起始位置排序
    intervals.sort((a, b) => a[0] - b[0]);
    const merged = [];
    for (const interval of intervals) {
        // 如果结果列表为空,或者当前区间的开始时间大于列表中最后一个区间的结束时间,
        // 则直接将当前区间加入结果列表
        if (!merged.length || merged[merged.length - 1][1] < interval[0]) {
            merged.push(interval);
        } else {
            // 否则,存在重叠区间,我们用两个区间的联合来更新列表中的最后一个区间
            merged[merged.length - 1][1] = Math.max(merged[merged.length - 1][1], interval[1]);
        }
    }
    return merged;
}
// 示例
const intervals = [[1, 3], [2, 6], [8, 10], [15, 18]];
const result = mergeOverlappingIntervals(intervals);
console.log(result);  // 输出: [[1, 6], [8, 10], [15, 18]]
1. 排序

首先,我们需要对输入的区间数组 intervals 进行排序。排序的目的是确保所有的区间按照它们的起始时间从小到大排列。这样可以帮助我们在后续的处理过程中更容易地检测到重叠的区间。

2. 初始化结果数组

创建一个空数组 merged,用于存放合并后的区间。

3. 遍历区间

接下来,我们遍历排序后的区间列表 intervals,对于每个区间 interval,我们检查它是否与 merged 数组中最后一个已经合并的区间重叠。

4. 检查重叠

对于每个区间 interval,我们有以下两种情况:

  1. 无重叠:如果 merged 数组为空,或者当前区间 interval 的起始时间大于 merged 数组中最后一个区间的结束时间,这意味着当前区间与之前的所有区间都没有重叠,可以直接将其添加到 merged 数组中。
if (!merged.length || merged[merged.length - 1][1] < interval[0]) {
    merged.push(interval);
}

2.有重叠:如果当前区间 intervalmerged 数组中最后一个区间存在重叠,我们需要更新 merged 数组中最后一个区间的结束时间,使其成为这两个区间结束时间中的最大值。

else {
    merged[merged.length - 1][1] = Math.max(merged[merged.length - 1][1], interval[1]);
}
5. 返回结果

遍历完成后,merged 数组中就包含了所有已经合并的不重叠区间。

最终咱们通过排序和一次遍历来高效地合并所有重叠的区间。排序确保了每次只检查当前区间与前一个区间的关系,而无需考虑后面的区间。成功解决了这道小米的算法题。

整个小米的面试大概就是这样,希望这份面经能够对正在秋招的你有所帮助。

另外有不懂之处欢迎在评论区留言,如果觉得文章对你学习有所帮助,还请”点赞+评论+收藏“一键三连,感谢支持!