人人(人人公司)✅
- 业务领域: 社交网络(人人网)、海外房产交易服务平台(北美地产 CMS 与经纪人 CRM 协同系统)
- 技术栈: Vue 3、Vue 2、Vue Router、Pinia/Vuex、TypeScript、Webpack/Vite、Node.js
- 团队规模: 前端研发团队约80人
- 办公地点: 北京(朝阳总部)、武汉
- 公司性质: 互联网上市公司(美股上市)
- 薪资水平: 校招15-26万,社招18-42万
岗位类型
- Vue 前端开发工程师 - 负责面向北美终端用户的房产检索 CMS 门户与移动响应式页面研发
- 中后台全栈开发工程师 - 负责房产经纪人 CRM 作业系统、房源合同流转与数据看板研发
- 前端组件库与工程化工程师 - 负责企业级通用复杂表格/表单物料库与微前端框架建设
技术特色
- 复杂表单与动态表头表格深度抽象: 针对海外房源多维度属性,深度运用 Vue 作用域插槽(Scoped Slots)与动态行列配置实现高性能表格。
- 跨时区与国际化多币种结算体系: 完善处理海外房产货币单位、度量衡(平方英尺/平方米)与本地化时区防抖转换。
- 高频响应式状态批处理优化: 深入探索 Vue 异步更新批处理队列、微任务
nextTick与多级过滤组件的状态解耦。
面试流程概览
校园招聘
- 简历筛选 → 在线笔试(JS/CSS/算法) → 技术一面 → 技术二面 → HR面试
- 总流程约2-3周
- 难度: 3/5星
- 通过率: 约18%
社会招聘
- 简历筛选 → 线下/线上笔试(核心算法与手写题) → 技术一面(基础语言追问与 CSS 布局) → 技术二面(Vue 框架底层与组件设计) → 技术三面(算法与系统架构) → HR面试
- 总流程约2周
- 难度: 4/5星
- 通过率: 约15%
题库
P0 必考知识点
函数柯里化与隐式类型转换:实现无限链式调用累加器 add(2)(3)(4) == 9?
答案
核心结论
满足 add(2)(3) == 5、add(2) + 3 == 5 且支持无限链式调用的核心在于:函数闭包持续保存所有历史入参,并重写该函数的 Symbol.toPrimitive 或 valueOf 与 toString 原型方法,使函数在参与相等比较(==)或算术运算(+)时自动触发隐式转换,返回累加计算值。
规范代码实现
function add(...args) {
// 1. 内部递归收集所有参数
const fn = function (...innerArgs) {
return add(...args, ...innerArgs)
}
// 2. 计算当前所有参数的和
const sum = args.reduce((acc, curr) => acc + curr, 0)
// 3. 拦截隐式类型转换(现代标准优先 Symbol.toPrimitive)
fn[Symbol.toPrimitive] = function (hint) {
return sum
}
// 兼容传统运行时的 valueOf 与 toString
fn.valueOf = function () {
return sum
}
fn.toString = function () {
return sum
}
return fn
}
// 测试用例
console.log(add(2)(3) == 5) // true
console.log(add(2) + 3 == 5) // true
console.log(add(2)(3)(4) == 9) // true
console.log(add(1)(2)(3)(4)(5) == 15) // true
面试官视角
面试官考察候选人对 JavaScript 函数式编程(Currying)、闭包记忆性以及 ECMAScript 对象到原始值转换协议(ToPrimitive 内部运算)的深层掌握。
Vue 中 vm.data 被频繁修改为何不会导致视图多次重绘?nextTick 底层机制是什么?
答案
核心结论
若响应式数据每改变一次就立即同步执行 DOM Diff 和更新,若同一事件循环中修改 1000 次数据,就会触发 1000 次 DOM 重排重绘,造成极严重的性能浪费。
Vue 内部采用了异步批处理更新队列机制(Async Batch Queue):响应式 setter 触发时,Watcher 不会立即更新,而是被塞入全局去重队列,利用微任务(Promise.resolve().then())将所有 DOM 更新合并在当前宏任务结束前统一批量执行。
工作原理流转
- Watcher 去重与缓存:
- 依赖收集触发
watcher.update(),内部调用queueWatcher(this)。 - 队列内部维护
has[id]哈希表,同一 Tick 内无论修改多少次同一 Watcher,仅会向队列塞入一次。
- 依赖收集触发
- 异步刷新通道降级决策:
nextTick(cb)负责将更新任务注入到异步微任务队列中。- 调度降级链:
Promise.then(首选微任务) →MutationObserver→setImmediate(IE/Node) →setTimeout(..., 0)(宏任务兜底)。
nextTick读取时机:- 开发者在修改数据后立即调用
nextTick(callback),该回调会被排在 Watcher 刷新 DOM 的任务之后。因此,在nextTick回调内部保证能够安全获取到渲染后的最新 DOM。
- 开发者在修改数据后立即调用
面试官视角
考查候选人对 Vue 响应式核心更新流程的全局认知,以及浏览器 Event Loop 中宏任务(MacroTask)、微任务(MicroTask)与渲染管道(Rendering Phase)先后执行时序的理解。
P1 高频知识点
Flex 布局实现:左侧固定 50px,中间与右侧自适应 1:2 分配且具备最小宽度限制?
答案
核心结论
利用 CSS Flex 弹性盒的 flex-grow、flex-shrink、flex-basis 复合属性配合 min-width 限制,可精准控制网格比例与边界防御。
规范 CSS 布局代码
<div class="container">
<div class="left">Left</div>
<div class="middle">Middle</div>
<div class="right">Right</div>
</div>
<style>
.container {
display: flex;
width: 100%;
}
.left {
/* 固定宽度 50px:不可拉伸,不可压缩,基础基准值 50px */
flex: 0 0 50px;
}
.middle {
/* 弹性比例 1:基准为 0,按 1 份瓜分剩余空间,最小宽度 50px */
flex: 1 1 0;
min-width: 50px;
}
.right {
/* 弹性比例 2:基准为 0,按 2 份瓜分剩余空间,最小宽度 100px */
flex: 2 1 0;
min-width: 100px;
}
</style>
延伸阅读
考察重点速览
- 必考知识点: JavaScript 柯里化与隐式转换、Vue 响应式与
nextTick批处理、Flex/Grid 现代布局、深浅拷贝与原型链。 - 高频面试题: 无限柯里化 add 实现、Vue 异步渲染队列原理、Flex 动态比例与最小宽度限制、前端缓存函数
memoize。 - 编程挑战: 数组去重与排序、数组扁平化 flat 实现、手写深克隆(处理循环引用)、实现表格动态列插槽。
备考建议
针对性准备策略
- 深挖 Vue 源码与生命周期: 人人公司核心采用 Vue 生态,务必通读 Vue 响应式原理、Diff 算法与组件设计模式。
- 扎实手写函数式与算法题: 人人面试包含多轮扎实的编码笔试,重点复习函数柯里化、闭包缓存、数组扁平与常见 CSS 居中/三角绘制技巧。
推荐准备资源
差异化准备建议
- 校招生: 掌握原生 JS/CSS 规范、常见算法手写及 Vue 常用 API。
- 社招生: 深入考察复杂中后台/CRM 系统业务抽象、通用组件封装设计与前端性能批处理优化。