阿里CTO|暑期实习|前端面试
总时长:2h
代码考核
- 手写代码时间:40min
- 拷问代码细节:1h
//题目1
//数组去除重复的项,即[‘1’,‘2’,'1',1,‘3’]——>[‘1’,‘2’,1,‘3’]
//这里'1'和1不同
//注:使用原生的方式,不使用set,map
const newArrToSet = (arr) => {
let res = [];
for(let i = 0; i < arr.length; i++){
if(!ans.includes(arr[i])){
ans.push(arr[i]);
}
}
}
- 这个普通写法的时间复杂度是O(n^2),面试官让优化时间复杂度,最后大抵懂了他的意思是可以手写一个Set()然后调用,不会手写Set(),问了里面的has函数是不是用hasownproperty()方法实现O(1)的查询,他说不是这样,那这题就寄了
//题目2:
//2个正整数字符串的相加,即‘1’+’19’——>’20’
// '123' + '5423'
// 力扣415原题
//隐式转换的写法
const stringAdds = (a, b) => {
return (+a) + (+b) + '';
}
// 常规的写法
// 大数相加
var addStrings = function(num1, num2) {
let res = [];
let add = 0;
let i = num1.length - 1;
let j = num2.length - 1;
// 注意这里三个条件,只要有任意一个触发就进入循环
// 有一个字符串未移动到最后一个元素,或者有进位
while(i >= 0 || j >= 0 || add !== 0){
// 这里如果是已经越界了,就变成0
// 没有越界,取字符对应的数字
let x = i >= 0 ? num1.charAt(i) - '0' : 0;
let y = j >= 0 ? num2.charAt(j) - '0' : 0;
// 加上进位
let sum = x + y + add;
res.push(sum % 10);
add = Math.floor(sum / 10);
i--;
j--;
}
return res.reverse().join('');
};
- 这里面试官没有细问,算是没问题
//题目3:
//写个转换函数,把一个JSON对象的key从横杠形式(Pascal)转换到小驼峰形式(Camel),即{“a_b”:1}——>{“aB”:1}
//注:考虑下嵌套,且不能改变原数据
//对象中的对象也要改吗?对象的属性值是数组或者对象
// { a: [1, { c: 1 }], b: undefined, c: [1, undefined,3] }
// 注意不同数据类型? obj/arr遍历
const formatToHump = (value) => {
return value.replace(/\_(\w)/g, (_, letter) => letter.toUpperCase())
}
// 改变原数据的写法
const formatTransferKey = (data) => {
if(data instanceof Array){
data.forEach(item => formatTransferKey(item))
} else if(data instanceof Object){
for(let key in data){
let hump = formatToHump(key);
data[hump] = data[key];
formatTransferKey(data[hump]);
}
} else if(typeof data === 'string'){
data = formatToHump(data);
}
formatToHump(data)
return data;
}
- 但是面试官让写的方法必须不能改变原来的数据,所以应该重新创建一个空数组或对象来存储转换后的数据
//题目4: 实现事件处理器 EventEmitter ,有如下功能
/**
* const event = new EventEmitter();
* const name = 'click';
* const callback = (name) => console.log(name);
* const callback1 = (callback1) => console.log('callback1');
* // 绑定事件
* event.on(name, callback);
* event.on(name, callback1);
* // 触发事件
* event.trigger(name, 'test'); // test callback1
* // 取消绑定
* event.off(name, callback);
* event.off(name, callback1);
*/
class EventEmitter {
constructor() {
this.eventList = {};
}
// 绑定,实现订阅
on (name, callback) {
// 下面这个if就是雷点
if(!this.eventList) {
this.eventList = Object.create(null);
}
if(!this.eventList[name]){
this.eventList[name] = [callback];
} else {
this.eventList[name].push(callback);
}
}
// 触发事件
trigger (name,...rest) {
if(!this.eventList[name]) return;
this.eventList[name].forEach(fn => fn.apply(this.rest));
}
// 取消订阅
off(name, callback){
if(!this.eventList[name]) return;
this.eventList[name] = this.eventList[type].filter(item => {
return item !== callback;
});
}
}
- 就因为create(null)和上面{}和上面写法不一致,被面试官连续拷问,以后再也不从网上背奇奇怪怪的代码了....当时大抵能理解是因为要创建纯净的空对象,不能从其他地方继承过来,但是一深挖就寄的挺彻底,确实是不应该掌握的东西
项目+八股
总计15min
问了get和post的区别,以及项目中遇到的最大困难,是怎么克服的
反问
技术栈:react和vue都有,react为主但不看重求职者会什么框架,都是互通的
面试评价:手写代码能力处于应届生中等偏上的水平,但不是top的那一类学生,还需要加强练习
总结
经过多次面试打击后心态明显转好,即便被狠狠拷打也和面试官有说有笑的,收到面试官的一丁点肯定也足够让我开心很久了。都到了春招这个时间段了,本来也不抱希望能够进,一周多后果然也挂掉了,不过这次面试确实是学到了很多

