阿里巴巴是通过师兄内推投递的,在系统开之前提前面了一轮,一共四轮技术面(含一轮交叉面)+ 一轮HR面。总的流程还算是比较快,一个月左右走完流程。内推的好处就是如果流程卡住,内推人可以帮忙催一催面试官尽早安排面试。
因为最开始没有做面试记录,凭靠记忆想到了下面几个题
promise
的原理,catch之后能调用then方法吗?
let promise = new Promise((resolve, reject) => {
reject(1);
});
// catch与then方法相同,都会返回一个promise对象,存在显式返回和隐式返回两种情况
// 1.隐式返回:返回一个resolve值为undefined的promise
promise.catch(err => {
console.log(err); // 1
}).then(resolve => {
console.log(resolve); // undefined
});
// 2.显式返回一个promise
promise.catch(err => {
return new Promise(resolve => {
console.log(err); // 1
resolve(2);
})
}).then(resolve => {
console.log(resolve); // 2
});
Domain、Path、Max-Age、Secure、HttpOnly
SameSite:
把三个值Strict、Lax、None的作用讲一下,chrome80版本把默认值None改为Lax造成什么影响。推荐阮一峰老师的文章:Cookie 的 SameSite 属性事件循环
的区别suspense
配合lazy
封装动态引入模块组件const myComponent = lazy(
() => import(
/* webpackChunkName: "index" */
'./index'
);
);
const myAsyncComponent = props => (
<Suspense fallback={<Loading />}>
<myComponent {...props} />
</Suspense>
);
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError() {
return { hasError: true };
}
render() {
// 如果捕捉到子组件错误,渲染回退页ErrorComponent
if (this.state.hasError) {
return <ErrorComponent />;
}
// 如果未捕捉到子组件错误,渲染子组件
return this.props.children;
}
}
// 用法
<ErrorBoundary>
<Child1 />
<Child2 />
...
</ErrorBoundary>
// 数据结构如下,点击一个地址获取到该地址的id,通过广度遍历去找到它所在的路径
const data = [{
id: '1',
name: '四川省',
children: [
{
id: '2',
name: '阿坝藏族自治州',
children: [
{
id: '3',
name: '汶川县'
}
]
}
]
}];
// 当时考虑到提高点击一级、二级地点(省、市)的遍历速度。实际在这里两种遍历差别不大。
function bfs(target, id) {
const stack = [...target];
while (stack.length) {
const current = stack.shift(); // 深度遍历的话换成pop
if (!current.path) {
current.path = new Array(current.id);
}
if (current.children) {
stack.push(...current.children.map(
item => {
return {
...item,
path: current.path.concat(new Array(item.id))
}
}
));
}
if (current.id === id) {
return current.path;
}
}
return undefined;
}
console.log(bfs(data, '3')); // [ '1', '2', '3' ]
三面四面都是围绕着个人项目和实习项目去问的,参考意义不大。到三面其实就是boss面了,主要看参加过的比赛和项目,如果参加过含金量比较高的比赛或者做过几个完整的项目(即使是一个完整的项目也比多个零散的拼凑项目强)会比较占优势。
HR在一个晚上突然打电话过来,直接进行了面试。问了专业相关的知识、如何学习前端、微信小程序设计大赛的收获、自己的优点、手里的offer(当时手里有个字节offer,就问了优先选择哪个,为什么)。面下来很快,大概半小时就结束了,没有感觉到HR很凶(网传阿里HR比较凶)。
周日上午一面,结束后面试官打电话约下午二面,晚上又接到电话约了HR面,整体流程非常快。
<div class="container">
<div class="left">
111
div>
<div class="right">
11111<br/>
11111
div>
div>
.container {
display: flex;
}
.left {
width: 200px;
background-color: blue;
}
.right {
flex: 1;
background-color: red;
}
.container {
position: relative;
width: 100%;
}
.left {
position: absolute;
width: 200px;
height: 100%;
background-color: blue;
}
.right {
width: calc(100% - 200px);
margin-left: 200px;
background-color: red;
}
.container {
display: table;
width: 100%;
}
.left {
display:table-cell;
width: 200px;
background-color: blue;
}
.right {
display:table-cell;
width: calc(100% - 200px);
background-color: red;
}
animation
去做offsetTop、offsetLeft
Object.prototype.toString.call()
,判断引用数据类型// 如果数组里全是字符串,可以用下面这个方法,在这里显然不行
arr.toString().split(',');
// 1 遍历
function bfs(arr) {
let arr2 = [];
let stark = [...arr];
while(stark.length) {
let item = stark.shift();
item instanceof Array ? stark.push(...item) : arr2.push(item);
}
return [...new Set(arr2)];
}
console.log(bfs(arr));
// 2 递归
function foo(arr, result = []) {
if (!(arr instanceof Array)) {
result.push(arr);
return;
}
arr.forEach(item => {
foo(item, result);
});
return result;
}
console.log(foo(arr));
const useInView = function(fn) {
useEffect(() => {
const innerFn = function() {
!document.hidden && fn();
}
// 绑定事件
document.addEventListener('visibilitychange', innerFn);
return (() => {
// 卸载时注销事件
document.removeEventListener('visibilitychange', innerFn);
});
});
}
function MyComponent() {
useInView(() => {
console.log(1111);
});
useInView(() => {
console.log(2222);
});
return (
<div></div>
);
}
props.children
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(function () {
console.log('setTimeout');
}, 0);
async1();
new Promise(function (resolve) {
console.log('promise1');
resolve();
}).then(function () {
console.log('promise2');
});
console.log('script end');
/**
* script start
* async1 start
* async2
* promise1
* script end
* promise2
* async1 end
* setTimeout
*/
console.log('start');
setTimeout(() => {
console.log('children2');
Promise.resolve().then(() => {console.log('children2-1')});
}, 0);
setTimeout(() => {
console.log('children3')
Promise.resolve().then(() => {console.log('children3-1')});
}, 0);
Promise.resolve().then(() => {console.log('children1')});
console.log('end');
// node11以下
/**
* start
* end
* children1
* children2
* children3
* children2-1
* children3-1
*/
// 浏览器及node11以上
/**
* start
* end
* children1
* children2
* children2-1
* children3
* children3-1
*/
function _new(obj, ...args) {
let newObj = {};
newObj.__proto__ = obj.prototype;
let ret = obj.call(newObj, ...args);
return typeof ret === 'object' ? ret : newObj;
}
纯聊天,结束后没有口头offer,上午面完的,下午HR加微信说面试通过,次日中午收到offer邮件。字节跳动的面试效率可以说是非常高了。
美团基本上隔两天约一轮面试,三轮技术+一轮HR。
const useMyDidUpdate = function(fn) {
const status = useRef(false);
useEffect(() => {
// 初始化时不执行
if (!status.current) {
status.current = true;
return;
}
fn();
});
}
<div class="container">
<div class="item">div>
div>
.container {
display: flex;
justify-content: center;
align-items: center;
}
.item {
}
.container {
display: flex;
}
.item {
margin:auto;
}
.container {
position: relative;
}
.item {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.container {
display: grid;
}
.item {
justify-self: center;
align-self: center;
}
.container {
display: table;
}
.item {
display: table-cell;
vertical-align: middle;
text-align: center;
}
let event = {
// 存放订阅事件
childrenList: {},
// 订阅函数
listen(type, fn) {
//如果chilidrenlist里这个缓存不存在,就先将它创建为空,为后续做准备
!this.childrenList[type] && (this.childrenList[type] = []);
// 判断传进来的是否是一个函数,若是就加到childrenList[type]下的数组中等待执行
typeof fn == 'function' && this.childrenList[type].push(fn);
// console.log(this.childrenList)
},
// 发布函数
touch(type) {
let fns = this.childrenList[type];
if (!fns && fns === 0) {
return false
}
fns.forEach(fn => {
fn.apply(this, [arguments]);
});
}
}
/**
* 创建一个订阅小红
*/
event.listen('小红', arguments => {
console.log(`${arguments[0]},${arguments[1]}`)
});
event.listen('小红', arguments => {
console.log(`大家注意,我们班的${arguments[0]}。${arguments[1]}`)
});
/**
* 创建一个订阅小明
*/
event.listen('小明', arguments => {
console.log(`${arguments[0]},${arguments[1]}`)
});
/**
* 向小红订阅事件发布消息
*/
event.touch('小红', '这次考试英语成绩年纪第一');
/**
* 向小明订阅事件发布消息
*/
event.touch('小明', '小明不出你的意料,你数学成绩还是倒数第一');
let arrA = [10, 11, 12, 13, 9, 8, 7,14];
function quickSort(arr) {
// 递归的终止条件
if (arr.length <= 1) {
return arr;
}
let begin = arr[0];
// 左指针
let i = 1;
// 右指针
let j = arr.length - 1;
while (i < j) {
while (arr[i] < begin && i < j) {
i ++;
}
while (arr[j] > begin && i < j) {
j --;
}
// 交换两个数的位置
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
let left, right;
if(arr[i] < begin){
left = arr.slice(1, i+1) ;
right = arr.slice(i+1, arr.length);
}
if(arr[i] >= begin){
left = arr.slice(1, i) ;
right = arr.slice(i, arr.length);
}
return [...quickSort(left), begin, ...quickSort(right)];
}
console.log(quickSort(arrA));
和上面两轮HR面一样,就是聊聊天。
以上就是本人春招面试的记录,由于流程比较长,上面这些都是印象比较深的题目。感觉阿里
的面试会稍微难一些,问的会比较有深度。字节跳动和美团
偏向于代码能力,这两个全程都是用牛客面试,美团
一面的时候还侧重考察了专业课水平。希望大家都可以早日拿到满意的offer。