首页 > 美团前端一面(凉)
头像
嚼嚼嚼
编辑于 2021-09-26 21:05
+ 关注

美团前端一面(凉)

部门:美团优选
时长:约70min
这次秋招第三次面试,终于遇到了一个女面试官。
做了自我介绍,似乎面试官没发现什么可以问的东西,就直接开始写算法题了hhh

算法题

写了两题,都比较简单。

题目1:同类项统计
给定数组['1a','2b','13c','5a'],数组元素的格式是一个数字(可能多位)前缀与一个字母的组合,输出出现次数最多的字母对应的前缀数字之和。
答:第一反应就用哈希表了。有其他思路欢迎指教。
//测试用例
const test=['1a','2b','13c','5a'];

const len=test.length;
const hash=new Map();
for(let i=0;i<len;i++){
    const strlen=test[i].length;
    //如果这个字符串中的字母还没作为键存储在哈希表中,就把他加进去
    if(!hash.has(test[i][strlen-1])){
        //哈希表中的值是一个数组,第一个元素代表出现的次数,第二个元素代表前缀数字之和
        //注意细节,slice方法的两个参数是能取到左不能取到右
        const arr=[1,parseInt(test[i].slice(0,strlen-1))];
        hash.set(test[i][strlen-1],arr);
    }else{
        //否则出现次数+1,前缀数字之和也要改变
        const arr=hash.get(test[i][strlen-1]);
        arr[0]++;
        arr[1]+=parseInt(test[i].slice(0,strlen-1));
        hash.set(test[i][strlen-1],arr);
    }
}
//接下来找出现次数最多的字母,并打印结果
let maxCount=0,res=0;
for(let key of hash.keys()){
    const arr=hash.get(key);
    if(arr[0]>maxCount){
        maxCount=arr[0];
        res=arr[1];
    }
}
console.log(res);

题目2:对象键名数组排序
给定一个对象,其中存储了世界富豪的名字(key)和资产(value),求排行榜(输出一个数组,其中是富豪的名字,按他们的资产从大到小排序)。
例如输入{bill:500,sam:480,roark:501},返回['roark','bill','sam']。
答:就是一个排序问题。我用了冒泡排序。
//测试用例
const test={bill:500,sam:480,roark:501,tom:999};
//Object.keys()方***返回一个由一个给定对象的自身可枚举属性组成的数组
//数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致
//arr=['bill','sam','roark','tom']
const arr=Object.keys(test);
const len=arr.length;
for(let i=0;i<len-1;i++){
    for(let j=0;j<len-i-1;j++){
        //一定要注意交换时用的序号是j不是i,面试时脑子太迷糊写错了,看半天都看不出来哪里错了
        if(test[arr[j]]<test[arr[j+1]]){
            let temp=arr[j];
            arr[j]=arr[j+1];
            arr[j+1]=temp;
        }
    }
}
console.log(arr);

JS基础

问题1:数据类型判断的方法?instanceof判断复杂数据类型的原理是什么?toString()和constructor有了解过吗?
答:①简单类型用typeof,复杂类型用instanceof。用typeof判断简单类型,除了null会返回object,其他都会返回正确的结果,如果判断复杂类型除了function,一律返回object。用instanceof可以检测某个实例是否是某个对象类型,如果用它来检测简单数据类型则始终返回false,因为基本类型不是对象。②MDN:instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。③查了MDN:默认情况下,toString() 方法被每个 Object 对象继承。如果此方法在自定义对象中未被覆盖,toString() 返回 "[object type]",其中 type 是对象的类型。例如
var o = new Object();
o.toString(); // returns [object Object]
可以通过 toString() 来获取每个对象的类型。为了每个对象都能通过 Object.prototype.toString() 来检测,需要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式来调用,传递要检查的对象作为第一个参数,称为 thisArg
var toString = Object.prototype.toString;

toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]

//Since JavaScript 1.8.5
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]
所有对象都会从它的原型上继承一个 constructor 属性,这个属性指向它的构造函数,可以利用这个属性判断数据类型。

问题2:说一下你对闭包的理解?用闭包有什么弊端?
答:①(按我自己的理解说的,如果有错或是有更好的理解欢迎指教)JS中每个函数都有一个作用域,现在假设一个作用域链上有一大一小两个作用域,其中小的作用域中引用了大作用域中的变量,则在小作用域被销毁之前大作用域不能被销毁,这就是闭包。②(摘自JS高级程序设计)闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存。过度使用闭包可能导致内存占用过多,我们建议读者只在绝对必要时再考虑使用闭包。虽然像V8等优化后的JS引擎会尝试回收被闭包占用的内存,但请大家还是要慎重使用闭包。

问题3:垃圾回收机制有了解吗?
答:(摘自JS高级程序设计)在JS中开发人员不再需要关注内存的使用问题,内存的分配及回收完全实现了自动管理。具体实现策略通常有两种:①标记清除(mark-and-sweep)(最常用):当变量进入环境(例如在函数中声明一个变量)时,就将这个变量标记为”进入环境”,理论上来说永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到它们,而当变量离开环境时,则将其标记为“离开环境”。垃圾收集器给内存中的所有变量加上标记(可以使用任何标记方式),然后去掉环境中的变量以及被环境中的变量引用的变量(大概就是闭包吧)的标记,而在此之后再被加上标记的变量被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后垃圾收集器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。②引用计数(reference counting)(不常用):引用计数的含义是跟踪记录每个值被引用的次数。如果某个值赋给某个变量,则其引用次数+1。如果包含对这个值的引用的变量又取得了另一个值,则这个值的引用次数-1。当某个值的引用次数变为0时就可以将其回收。但是会有循环引用的问题。

问题4:new的原理?
①new是什么:JavaScript中,new操作符用于创建一个给定构造函数的实例对象。如果在构造函数中返回一个原始值(例如return 0;),这个返回值并没有作用。如果构造函数返回值为一个对象,那么这个返回值会被正常使用。
②new的工作流程:
  • 创建一个新的对象obj

  • 将对象与构建函数通过原型链连接起来

  • 将构建函数中的this绑定到新建的对象obj上

  • 根据构建函数返回类型作判断,如果是原始值则被忽略,如果是返回对象,需要正常处理
③手写new
function mynew(Func, ...args) {
    // 1.创建一个新对象
    const obj = {}
    // 2.新对象原型指向构造函数原型对象
    obj.__proto__ = Func.prototype
    // 3.将构建函数的this指向新对象
    let result = Func.apply(obj, args)
    // 4.根据返回值判断
    return result instanceof Object ? result : obj
}

问题5:构造函数,实例对象和原型对象是怎么挂载的
答:直接上JS高程的图,注意构造函数和实例对象不直接相连,注意各个对象相互关联的属性名都叫啥。


问题6:const,let,var的区别?
答:放一下自己的笔记,如果有错欢迎指正。


问题7:箭头函数和普通函数的区别?
答:(摘自ES6标准入门)①(重点)函数体内的this对象就是定义时所在的对象,而不是使用时所在的对象。通常this指向是可变的,但在箭头函数中它是固定的。②不可以当作构造函数。也就是说不能使用new命令,否则会报错。③不可以使用arguments对象,该对象在函数体内不存在。如果要用可以用rest参数代替。④不可以使用yield命令,因此箭头函数不能用作Generator函数。

CSS

问题:实现一个3×3九宫格你选用的方法?
答:感觉这题答的不太好,说了可以用grid,flex,或者直接三个div每个包含三个span。

总结

17号面试,现在还没啥消息,慢慢等吧。
面试官说我基础知识还是得补补,确实得补补,嘤。

更多模拟面试

全部评论

(11) 回帖
加载中...
话题 回帖

近期热帖

历年真题 真题热练榜 24小时
技术(软件)/信息技术类
查看全部

热门推荐