阿里盒马、腾讯小程序团队 —— 小菜鸡自闭の面经??(等HRing...)
2020/3/27 11:07:06
本文主要是介绍阿里盒马、腾讯小程序团队 —— 小菜鸡自闭の面经??(等HRing...),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
啰嗦の前言
俺这只小菜鸡🐔终于也快迎来曙光了!😀
俺现在是一名大三学生,渴望能获得一份大厂的实习机会呜呜呜,所以不自量力的投了一下阿里跟腾讯。阿里是提前批就开始面了的。很多部门都面了一下下,面了啥也忘了哈哈哈哈。也多亏了提前批,让俺知道哪些地方还需要再补补。
阿里这边最终选择了盒马,盒马的面试官都好好,好和蔼,给了好多建议,没有因为我菜就嫌弃我呜呜呜,太感动了。而且!看到这张“屁股脸”难道不想加入换一套限量公仔/手办吗!
个人の想法
- 我觉得面试更像是一次学习的机会,可以查漏补缺,之后自己深入学习更多的东西
- 我还是觉得大厂面试,还是得有一个自己熟悉的、参与度高的项目来展开,因为还是很多面试官会选择问问项目经历来了解我们。
- 不会就是不会哈哈哈哈,老实承认就好,之后自己下去再找找资料补一补就好!不必沉浸在悲伤之中
- 面试完之后,如果有问题,尽量积极主动的去寻找面试官请教,不要觉得不好意思或者说不敢这样子,我觉得就算即便是挂了也好,也可以请教一下学到更多的东东,不至于一场面试下来颗粒无收
阿里の盒马
初面
初面是聊得最久的一次了,一个多小时了吧,不过初面的面试官真的很让人感动一直在鼓励我,“好啊好啊”,“没关系没关系”,啊太棒了,给俺这个小菜鸡很多信心hhhh
- 输入url到页面展示
- 浏览器存储
- 如何实现继承
- 跨域,常用哪个,解释一下
- 缓存
- 重绘回流
- 性能优化
- React优势
- React生命周期
- React最佳实践
- React新特性
- 如果列表组件要新增一些内容,例如标题,简介等,你会怎么对代码进行修改(容器组件 -> 展示组件)
- csrf 和 xss
- flex
- 判断是否为数组
- typeof arr === 'object'
- 浏览器事件循环,node事件循环
- 事件委托
- webpack流程,插件
- koa源码
- koa洋葱模型
- mobx原理
- 首屏优化
- async/await Promise
- 盒模型
- babel原理
- Taro原理
一面
一面俺就放放笔试题还有俺自己做的情况吧哈哈哈哈,一面的面试官跟俺说拓扑排序,俺才知道原来还有这种东西(流泪...
笔试题目
- 给定一个链表,判断链表中是否有环,比如下图这种即为有环链表。 加分项:使用空间复杂度 O(1) 实现
- 分析一个项目的依赖结构,并按依赖优先级排序。 已知一个项目的依赖结构,期望在前端通过 loader 的方式异步加载相关的组件,而我们期望依赖在加载的过程中:
- 每一个依赖被加载后都会被立刻执行,那么如果要争取加载一个依赖,则其子依赖都应该优先被加载
- 每一个依赖不希望在钱多出现冗余的情况,若依赖出现多版本的情况,则默认使用更新的版本,比如已知项目依赖结构为(其中 @ 后面的为依赖版本号):
ProjectA - a@0.1.0 - d@0.2.0 - c@0.1.0 - b@0.1.1 - e@0.1.2 - c@0.1.2 - c@0.2.0 复制代码
则其中一种输出的依赖优先级排序为:
['d@0.2.0', 'c@0.2.0', 'a@0.1.0', 'e@0.1.2', 'b@0.1.1']
输出分析: 为了让 a 加载后可以争取执行,则必须先加载 d 和 c,b 的加载同理,又因为在整个依赖关系下,c 的最新版本为 0.2.0 于是有了如上的输出结果。
- 请用 React 实现一个搜索框组件,功能包括:
- 输入文本字数限制
- 可配置输入文本约束,比如仅限输入数字
- 用户输入时可支持关键字搜索,并出现下拉框展示相关项
俺的答案
- 第一题leetcode原题来的,环形链表好像是,可以用快慢指针或者简单的集合
const cycle1 = function (node) { let set = new Set() while (node) { if (set.has(node)) return true else set.add(node) node = node.next } return false }; const cycle2 = function (node) { let start = node let end = node.next while (start !== end) { // 没有环就null if (end === null || end.next === null) return false start = start.next end = end.next.next } return true } 复制代码
- 第二题的话我拿到题目第一个想到的就是DFS来寻找那些依赖,然后最后再对依赖这些进行版本比较(其实应该用集合、还有拓扑排序来优化)
这题有大佬在评论区指出错误啦!之前那个版本是比较字符串,但是忽略了多位数字版本的情况,例如
b@0.2.22
与b@0.2.3
,结果应该是前者,但之前版本是输出后者,现在修改了一下!好嘞!
function update(npmList) { let versions = {} let res = [] // 比较版本号 function cmp(a, b) { const versionListA = getVersion(a).split('.') const versionListB = getVersion(b).split('.') for (let index = 0; index < 3; index++) { const versionA = parseInt(versionListA[index]) const versionB = parseInt(versionListB[index]) if (versionA > versionB) return a else if (versionA === versionB) continue else return b } return a } // 获得版本号 function getVersion(str) { return str.substr(str.indexOf('@') + 1) } function dfs(npmList) { if (npmList.length === 0) return npmList.forEach((npm) => { const { name, deps = [] } = npm // 先遍历他们的依赖 dfs(deps) let key = name.substr(0, name.indexOf('@')) // 如果依赖不存在则添加,若已存在,则取最新版 if (!versions[key]) { versions[key] = name } else { versions[key] = cmp(versions[key], name) } // 添加进最后的加载列表 res.push(key) }) return } dfs(npmList) // 去除重复项,然后将包名转换为依赖名,eg: a -> a@0.1.0 return [...new Set(res)].map(key => versions[key]) } 复制代码
- 第三题的话,我粗略写了一下噗,写的也不是很好,用React整的
// 第三题React部分第三题React部分第三题React部分第三题React部分第三题React部分 import React, { Component } from 'react'; import './input.css' function debounce(fn, delay = 500) { let timeout = null return function (e, ...args) { e.persist && e.persist() timeout && clearTimeout(timeout) timeout = setTimeout(() => { fn.call(this, e, ...args) }, delay) } } class Tips extends Component { render() { const { tipsList } = this.props return tipsList && tipsList.length !== 0 ? ( <div className="tips__container"> {tipsList.map((item, index) => { return ( <a href="#" key={index} className="link">{item}</a> ) })} </div> ) : <div></div> } } export default class Input extends Component { constructor(props) { super(props); this.state = { keyWords: [ '前端工程师1', '前端高级开发1', '后端工程师1', '测试开发1', '项目主管1', 'dress', 'Recent', '123456', 'awdad1' ], inputValue: '', inputType: 'text', inputMaxLen: 20, wordsList: [] } this.handleInput = debounce(this.handleInput, 200) this.handleMaxLenChange = debounce(this.handleMaxLenChange, 400) } handleInput = (e) => { const { target: { value } } = e const { keyWords } = this.state const tipsList = !value ? [] : keyWords.filter(item => { const res = item.search(new RegExp(value, 'i')) return res !== -1 }) this.setState({ inputValue: value, tipsList }) } handleTypeClick = (e) => { const { target: { name } } = e this.setState({ inputType: name }) } handleMaxLenChange = (e) => { const { target: { value } } = e const { inputValue } = this.state const newInputValue = inputValue.substr(0, +value) // 如果设置最大长度小于现在关键词的长度,则截取一下 this.input.value = newInputValue this.setState({ inputMaxLen: value, inputValue: newInputValue }) } render() { const { tipsList, inputType, inputMaxLen } = this.state return ( <div className="container"> <div className="control__container" onClick={this.handleTypeClick}> <button name="text">文本</button> <button name="number">数字</button> <span>最大长度: </span> <input type="number" placeholder="默认: 20" onInput={this.handleMaxLenChange} /> </div> <div className="input__container"> <div className="input__wrap"> <input ref={input => this.input = input} placeholder="请输入关键词" type={inputType} maxLength={inputMaxLen} onInput={this.handleInput} /> <button>搜索</button> </div> <Tips tipsList={tipsList} /> </div> </div> ) } } 复制代码
// 第三题CSS部分第三题CSS部分第三题CSS部分第三题CSS部分第三题CSS部分第三题CSS部分 .container { width: 600px; height: 400px; margin: 0 auto; padding: 30px; background: #fff; } .input__container { margin-top: 30px; } .input__wrap { display: flex; align-items: center; } .input__wrap input { box-sizing: border-box; width: 85%; height: 50px; padding: 0 10px; border: #666 1px solid; border-right: 0; outline: none; } .input__wrap button { cursor: pointer; box-sizing: border-box; width: 15%; height: 50px; color: #fff; font-size: 20px; border: none; border: #666 1px solid; outline: none; background: #1890ff; } .control__container { display: flex; align-items: center; } .control__container button { cursor: pointer; width: 50px; height: 30px; margin-right: 10px; color: #fff; outline: none; border: #333 1px solid; border-radius: 8px; background: #1890ff; } .control__container span { margin-left: auto; margin-right: 10px; color: #666; font-size: 14px; } .tips__container { overflow-y: scroll; max-height: 200px; border: #333 1px solid; border-top: 0; } .tips__container .link { display: block; height: 30px; padding: 5px 10px; color: #666; line-height: 30px; text-decoration: none; } .tips__container .link:hover { color: #fff; background: #666; } input::-webkit-outer-spin-button, input::-webkit-inner-spin-button { display: none; } 复制代码
二面
二面主要是结合项目来问的,抓住一个功能发散开来,例如我项目的聊天室的功能,吓得我好慌好慌hhh,不过面试官人很好一直引导我,特别是那些场景题,引导我去思考,啊,太感动了!!!
- 项目の各种东东
- 聊天私聊怎么做
- 聊天记录未读消息怎么做
- 聊天离线信息处理
- session会话管理如何实现(用户登录后,打开新标签页输入url访问资源)
- 访问资源权限控制
- 事件队列题
- websocket如何连接
- 做题系统组件的设计与拓展(拓展更多类型的题目,如何设计组件)
- 用户鉴权系统设计
- 为什么密码表跟用户信息表分开放
- 数据库表的设计
三面
这一面也是结合项目来问的。啊,三面的面试官真的太好了,期初我的小项目没什么难点(我都以为凉透透了呜呜呜),然后面试官给了提了几个建议,让我多去深入思考思考,面试完之后去找他请教问题,也一直很有耐心给我指导指导,啊,太棒了吧🤭
- 项目の各种东东
- 飞猪为什么挂了
- 项目难点
- 小程序登录怎么做的
- 封装了什么组件
- 建议:在线阅卷、批注、修改错别字等(canvas绘制)
- 建议:实时监控每个同学的进度(选择答案后之后教师端更新/摄像头监控)
- a与b聊天,将他们的记录,多选,然后合并发给c,如何设计
- 除了编译成小程序,有试过app吗
四面
四面应该是总监面,还是得感谢三面的面试官给我提的建议,之后做出来之后,发现这个东东可以作为项目的一个难点来吹哈哈哈!四面主要还是围绕项目来问,我个人觉得关注的更是自己的思维、对技术的认识、对自己未来的发展规划等宏观的内容
- 项目难点(canvas绘制公式
- websocket实现,聊天功能的实现(心跳检测,断线重连
- 项目の细节
- 聊天信息的一致性,时序性
- 目标、具体想通过实习学到什么
- 技术规划,之后学些什么
五面
五面是交叉面,心惊胆跳呜呜呜,希望不要挂我...五面问的大多是基础方面的内容,不过也是结合项目来问的,这一面面试官主要关注的是
性能
方面的内容,例如数据埋点啊、页面加载时间、接口响应时间等一系列关于性能方面的问题,他希望的是数据量化的一个东东,具体的实现,达成了什么目标等
- 项目做了那些事情
- 小程序运行池
- 小程序和H5的区别
- 缓存存在哪(强缓存、协商缓存分别通过什么字段保存
- React与Vue的区别
- React的优势
- Taro编译的机制
- Taro支持的端有哪些
- node的机制、优势
- 项目的难点,如何解决,遇到的问题
- 如何监控性能
- 尝试做了哪些性能上的优化
- 收集用户信息?数据埋点?性能指标?量化指标?
- 资源大小,加载速度,页面渲染时间,接口访问时间
- 如何优化node后台的接口(sql优化,表结构重写
- 使用什么服务器,部署在什么操作系统上
- 多人同时访问接口测试过吗?最高承载多少
- webpack如何减小资源打包大小
- 擅长什么
- 你的优势是什么
- 目标?规划?
腾讯の小程序
一面
一面是笔试 + 面试,俺也放放题目跟俺的答案吧!
笔试题目
- 实现⼀个函数 reverse(a, n) ,反转⼀个含有 n 个整数的数组 a(直接在数组a上操作,元素交换次数 尽可能少,不能使⽤js Array 类内置属性和⽅法)。
- 实现⼀个函数 countLongest(tree) ,输⼊⼀棵⼆叉树,返回⼆叉树中距离最⻓的两个叶⼦节点之间 的距离。
var x = [0, 1, 2, 3] reverse(x, 4) // x = [3, 2, 1, 0] var y = [1, 2, 3, 4, 1] reverse(y, 5) // y = [1, 4, 3, 2, 1] var tree1 = { value: 1, left: { value: 2 }, right: { value: 3 } } countLongest(tree1) // 2 var tree2 = { value: 1, left: { value: 2, left: { value: 3, left: { value: 6 } }, right: { value: 4 } }, right: { value: 5 } } countLongest(tree2) // 4 复制代码
- 在前端开发中,通常会把多个js⽂件合并成⼀个⽂件,以减少⽹络请求次数,达到优化加载速度的⽬ 的,但是当⽂件之间存在依赖关系时,对js合并的顺序,会有⼀定的要求,⽐如 A.js 依赖了 B.js,那打 包后的⽂件,B.js 需要排在 A.js 的前⾯。 实现⼀个函数 resolve(tree) ,根据js的依赖关系树 tree,输出合理的打包顺序的数组(结果可能不 唯⼀,输出其中⼀种即可)。
样例
var tree1 = { name: 'main.js', require: [{ name: 'A.js' }, { name: 'B.js' }] } resolve(tree1) // ['A.js', 'B.js', 'main.js'] var tree2 = { name: 'page.js', require: [{ name: 'A.js', require: [{ name: 'B.js', require: [{ name: 'C.js' }] }] }, { name: 'D.js', require: [{ name: 'C.js' }, { name: 'E.js' }] }] } resolve(tree2) // ['C.js', 'E.js', 'D.js', 'B.js', 'A.js', 'page.js'] 复制代码
- 给定⼀个整数数组 a,实现⼀个函数 countMax(a) ,计算出从 a 中选择出多个不相邻元素组成最⼤的 和是多少。
样例
var x = [1, 4, 5, 3] countMax(x) // 7 var y = [3, 12, 6, 2, 4] countMax(y) // 16 复制代码
俺的答案
- 就是简单的倒置hhh
function reverse(arr) { let len = arr.length for (let start = 0; start < Math.floor(len / 2); start++) { let end = len - start - 1; [arr[start], arr[end]] = [arr[end], arr[start]] } return arr } 复制代码
- 这题是leetcode原题好像,就算算深度
function countLongest(tree) { if (!tree) return 0 let res = 0 function dfs(node) { if (!node) return 0 const leftMax = dfs(node.left) const rightMax = dfs(node.right) res = Math.max(leftMax + rightMax, res) return Math.max(leftMax, rightMax) + 1 } dfs(tree) return res } console.log(countLongest({ value: 1, left: { value: 2 }, right: { value: 3 } })) console.log(countLongest({ value: 1, left: { value: 2, left: { value: 3, left: { value: 6 } }, right: { value: 4 } }, right: { value: 5 } })) 复制代码
- 第三题是不是很眼熟哈哈哈,跟盒马一面的笔试题好像(其实我发现很多面试笔试题都有这相关的影子)还是DFS来找
function resolve(npmList) { const res = [] function dfs(npmList) { if (npmList.length === 0) return npmList.forEach((npm) => { const { name, require = [] } = npm dfs(require) !res.includes(name) && res.push(name) }) return } dfs(npmList) return res } console.log(resolve([{ name: 'page.js', require: [{ name: 'A.js', require: [{ name: 'B.js', require: [{ name: 'C.js' }] }] }, { name: 'D.js', require: [{ name: 'C.js' }, { name: 'E.js' }] }] }])) 复制代码
- 用动态规划来找
function countMax(arr) { const len = arr.length const dp = new Array(len).fill(0); dp[0] = arr[0] dp[1] = arr[1] dp[2] = arr[0] + arr[2] for (let i = 3; i < len; i++) { dp[i] = arr[i] + Math.max(dp[i - 2], dp[i - 3]) } return Math.max(dp[len - 1], dp[len - 2]) } console.log(countMax2([1, 4, 5, 3])) console.log(countMax2([3, 12, 6, 2, 4])) 复制代码
面试内容
- 项目
- 为什么用token不用cookie
- 跨域(前端跟前端的跨域,iframe之间)
- xss
- React与Vue的对比
- Taro与其他多端框架
- 主要还是项目发散
- 如何实现轮播图
二面
二面基本都是一些基础吧,但是就有些地方会深入去挖这样子
- https原理,握手过程(何时对称/非对称,谁先谁后,为什么这样)
- 常见的优化
- webp格式优化了多少
- 缓存以键值形式存在浏览器,键是什么,值是什么
- 设计一个缓存策略,(hash值)
- React的key
- React与Vue的区别
- Taro与小程序官方框架的区别
- 小程序运行池
- React列表key固定,顺序调换会渲染吗(不会)
- 如何判断性能瓶颈
- 项目の各种东东
三面
三面感觉还不够二面难,问的比较常见吧应该说,然后也是问问项目这样子
- 算法:判断数组中是否存在两个数相加等于目标值,给出多种思路与时间空间复杂度(暴力循环,排序后循环剪枝,动态规划)
- es6的class如何实现私有变量(symbol + 闭包)
- 如何进行性能监控
- 常见的性能优化方法
- 内存泄露如何发现,如何解决
- 垃圾回收机制
- 跨域(cors + jsonp + 其他不常见的跨域方法)
- 浏览器缓存
- 实现深拷贝,深拷贝的用途
- xss、csrf
- cookie与token的工作原理,区别,如何设计
- http1.1、http2.0
- http无状态
- websocket是什么协议,如何连接
- websocket有什么优势,对比轮训呢
- 事件循环
- setTimeout是否准时,如果不是则应该提前还是延迟
- webpack流程
- 常见的http状态码
- babel原理、taro原理
- map中的键值会不会被回收(weakMap,weakSet等)
- 项目....难点、设计、收获
- 平时如何学习
菜鸡の总结
自己还是太菜了呜呜呜😭
希望HR面的时候放俺一条生路可好...
还是觉得面试不要慌,慌也没有用,不如让自己冷静一下,然后每次回答问题的时候想一下应该怎么表达会更清晰(我就是表达不行,面试官都理解不了俺在说啥hhhhh)。问的问题除了结合项目来发散,还喜欢出一些情景题,现场设计一个组件啊、一个缓存策略啊、一套权限控制啊之类的内容。到时候就随机应变,想一下再说出来就好啦!
最后还是祝愿大家春招早日结束战斗!!拿到心爱的offer!!
这篇关于阿里盒马、腾讯小程序团队 —— 小菜鸡自闭の面经??(等HRing...)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-04微信小程序如何实现点击图片查看大图功能-icode9专业技术文章分享
- 2024-09-28uniapp 小程序获取到数据库的换行符怎么展示-icode9专业技术文章分享
- 2024-09-20微信小程序全栈项目实战:从零开始的全面指南
- 2024-09-20微信小程序项目实战:零基础入门教程
- 2024-09-19微信小程序项目中miniprogram_npm文件跟node_modules文件的差别-icode9专业技术文章分享
- 2024-08-27小程序 单行显示,超出部分省略号显示的方法代码-icode9专业技术文章分享
- 2024-08-27微信小程序如何获取到特种设备的刘海屏高度-icode9专业技术文章分享
- 2024-08-27微信小程序如何获取苹果手机底部一横线高度信息方法代码-icode9专业技术文章分享
- 2024-08-27微信小程序 顶部状态栏标签背景为none但还是看不到状态栏什么原因-icode9专业技术文章分享
- 2024-08-21微信小程序全栈入门:从零开始的一站式指南