美团前端一面(凉)
部门:美团优选
时长:约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);
给定一个对象,其中存储了世界富豪的名字(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的工作流程:
问题5:构造函数,实例对象和原型对象是怎么挂载的 

-
创建一个新的对象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 }
答:直接上JS高程的图,注意构造函数和实例对象不直接相连,注意各个对象相互关联的属性名都叫啥。
问题6:const,let,var的区别?
答:放一下自己的笔记,如果有错欢迎指正。
问题7:箭头函数和普通函数的区别?
答:(摘自ES6标准入门)①(重点)函数体内的this对象就是定义时所在的对象,而不是使用时所在的对象。通常this指向是可变的,但在箭头函数中它是固定的。②不可以当作构造函数。也就是说不能使用new命令,否则会报错。③不可以使用arguments对象,该对象在函数体内不存在。如果要用可以用rest参数代替。④不可以使用yield命令,因此箭头函数不能用作Generator函数。
答:(摘自ES6标准入门)①(重点)函数体内的this对象就是定义时所在的对象,而不是使用时所在的对象。通常this指向是可变的,但在箭头函数中它是固定的。②不可以当作构造函数。也就是说不能使用new命令,否则会报错。③不可以使用arguments对象,该对象在函数体内不存在。如果要用可以用rest参数代替。④不可以使用yield命令,因此箭头函数不能用作Generator函数。
CSS
问题:实现一个3×3九宫格你选用的方法?
答:感觉这题答的不太好,说了可以用grid,flex,或者直接三个div每个包含三个span。
总结
17号面试,现在还没啥消息,慢慢等吧。
面试官说我基础知识还是得补补,确实得补补,嘤。
#美团面试##面经##校招##美团##前端工程师#