欢聚时代2018校招笔试题-web前端 B卷,这套题在当年的前端求职圈里讨论度不低。很多人拿到手第一反应是"怎么还有这么多基础题",第二反应才是"原来框架题这么少"。我算是亲身刷过这套题的人,后来也帮朋友复盘过好几遍。今天不整虚的,就结合这套B卷的考察逻辑,聊聊前端校招笔试到底在筛什么样的人,以及每一类题目背后的出题意图和应对思路。
先说结论:这套题的核心不是考察你用了什么框架,而是考察你对前端这个领域的基础认知是否完整、对浏览器和网络的理解是否到位、对JavaScript语言本身是否有足够深的掌握。2018年的时候Vue和React已经很火了,但笔试题里并没有出现"讲讲Vue的响应式原理"这种题。这说明公司在校招笔试这个环节,默认你是一张白纸,他们要的不是你会什么框架,而是你有没有成为一张高级白纸的潜力。
1. 整体试卷的面貌与出题逻辑
整套B卷拿到手,给人的第一感觉是:题目量不小,但难度曲线还算合理。大致划分的话,可以分成三个板块:
| 板块 | 考察重点 | 题型 |
|---|---|---|
| 基础三件套 | HTML、CSS、JavaScript核心 | 选择题、填空题 |
| 进阶理解 | 浏览器渲染、网络协议、性能优化 | 简答题、判断题 |
| 逻辑与代码 | 算法思想、代码输出、手写能力 | 编程题、读代码题 |
如果你之前刷过其他公司的笔试题,会发现这个结构几乎是2018年前后一线互联网公司的标配。但欢聚时代这套题有一个明显特点:非常强调"实际场景下的基础知识运用"。比如有的题目直接给一段业务中常见的代码片段,让你判断输出结果;有的题目会结合直播业务场景,问弹幕频繁插入DOM如何优化。这种出题方式其实比单纯背概念要难得多。
为什么在线笔试要这么设计?我理解是这两年校招简历里"熟悉Vue/React""了解Webpack"的人实在太多了,但真正能解释清楚浏览器地址栏输入URL后发生了什么的候选人是少数。笔试环节作为第一道筛选,必须用基础题把那些简历包装得很好的人筛掉,留下真正下过功夫的。所以你会发现,整套题几乎很少考察某个框架的具体API,因为框架API是可以通过短期记忆应付过去的,而基础能力的差异是装不出来的。
还有一个值得注意的点:这套题没有太多"偏题怪题"。比如罕见的CSS属性、冷门的JS方法,基本没有出现。所有考点都能在标准的学习路径里找到对应章节。这其实也是大厂笔试题的一个风格取向——不靠偏题难倒你,而是靠基础题的深度和广度拉开差距。
2. CSS考察:从盒模型到BFC,看似送分实则暗藏分水岭
CSS部分在B卷里占的分数不算最多,但丢分率出乎意料地高。我后来看了几个人的成绩单,发现CSS其实是区分度最大的一个环节。原因很纯粹——大部分人认为CSS很简单,不值得花精力深挖,结果题目稍微一变化就暴露了理解深度不够。
2.1 盒模型的计算题是绕不开的坎
B卷里有一道选择题,给你一个div,设置了width、padding和border,然后问你实际占用的宽度是多少。这道题本身不难,但它同时考察了box-sizing: content-box和box-sizing: border-box两种模式下的差异。如果你平时写样式都是用全局reset把box-sizing统一设置成border-box,很可能对content-box的默认计算方式就不敏感了。
实际的考点是这样的:
- 默认content-box模式下,
width: 200px指的是内容区的宽度。实际渲染宽度 = width + padding + border。 - border-box模式下,
width: 200px指的是最终盒子的总宽度,内容区会被压缩。
如果题目再加一个margin,那实际占用空间还得加上margin值。这里容易出错的地方在于:很多人混淆了"渲染区域"和"占用空间"这两个概念。渲染区域受box-sizing影响,而margin导致的占用空间始终是向外扩展的。
我建议面试者把盒模型的理解粒度细化到四个层面:
- 内容区(content)
- 内边距(padding)
- 边框(border)
- 外边距(margin)
然后在心里明确一个问题:问的是"整个盒子在页面上占据的矩形区域面积",还是"盒子的width属性对应的区域"?这两个答案在content-box下是完全不同的。
2.2 垂直居中的多种实现方式
B卷里有一道简答题,题目大意是:给定一个父容器,宽高已知,子元素宽高未知,如何实现水平垂直居中?请写出尽可能多的实现方式。
这道题考察的本质不是让你背代码,而是考察你对CSS布局演进的了解程度。2018年这个时间节点,Flexbox已经全面普及,Grid也开始进入浏览器。所以这道题的完整回答至少应该包含三个时代:
- 定位 + 负margin:利用父元素relative定位,子元素absolute定位,left和top设为50%,再用负margin回移自己宽高的一半。缺点是要求子元素宽高确定。
- 定位 + transform:同上,只不过回移用的是
translate(-50%, -50%),优点是不需要知道子元素的宽高。 - Flexbox方案:父元素
display: flex; align-items: center; justify-content: center;,一个字,爽。 - 更进一步,Grid方案:父元素
display: grid; place-items: center;,是当时比较新的写法。
这道题的加分项在于:你能不能说清楚每种方案的适用场景和局限。比如position: absolute方案会让子元素脱离文档流,可能产生层叠上下文问题;transform方案的translate百分比是相对自身尺寸的,所以可以用但要注意对动画性能的影响;Flexbox方案对子元素的margin处理有一定影响,等等。这些讨论才是考官真正想看到的东西。
2.3 BFC:一个高频但也容易被误读的概念
B卷里还有一道判断题,说一个元素设置了overflow: hidden之后会创建一个BFC。很多人看到"overflow: hidden"就直接判对了,但仔细琢磨一下,这句话其实只说对了一半。准确的说法是:除了visible之外的值都能触发BFC,而overflow: hidden只是其中一种常见手段。但题目本身没有错,问题出在"理解了用overflow hidden可以解决塌陷问题,却没理解为什么"的层次上。
BFC(Block Formatting Context,块级格式化上下文)的考察点一般集中在三个场景:
- 防止margin塌陷
- 清除浮动
- 阻止元素被浮动元素覆盖
我建议复习BFC的时候不要死记触发条件(哪些属性值能触发),而是从"BFC是一个独立的渲染区域"这个定义出发去推导:既然内部元素不会影响外部,margin塌陷自然被解决;既然这个区域和外部隔离,浮动的子元素就不会逃出去撑破父容器;既然区域本身是一个独立的渲染上下文,那么它和浮动元素的关系就变成了普通文档流与浮动的规则,而不是父子关系里的覆盖规则。
从定义推导应用场景,比背诵三条结论要可靠很多。这道题其实就是在测你的理解是前者还是后者。
3. JavaScript核心机制:笔试拉开差距的主战场
JavaScript部分是整套B卷的权重之王。选择题、填空题、读代码题、手写编程题,几乎每一个板块都有它的身影。而且这部分题目明显经过精心设计,不是简单背概念就能应付的。我刷完最大的感受是:它考察的是"你对JavaScript底层机制的理解是否能支撑你在真实开发中写出靠谱代码"。
3.1 事件循环与执行顺序
B卷里有一道很经典的读代码题,考的是Promise、setTimeout和同步代码的执行顺序。这种题当年已经不算新鲜了,但依然很多人做错。原因在于,宏观上知道"JS是单线程的""有事件循环",但微观上对任务队列的细节分类不够清楚。
这道题的关键知识点可以拆成几个层次:
- 同步代码先执行
- 微任务(microtask)在当前宏任务(macrotask)结束前执行
- setTimeout的回调是宏任务,会在下一轮事件循环中执行
- Promise的resolve回调是微任务,比setTimeout更早执行
实际代码可能是这样的:
console.log('script start'); setTimeout(() => { console.log('setTimeout'); }, 0); Promise.resolve().then(() => { console.log('promise1'); }).then(() => { console.log('promise2'); }); console.log('script end');正确的输出顺序是:script start、script end、promise1、promise2、setTimeout。
这道题的坑点在于,很多人认为setTimeout(0)是立即执行,但实际上它只是把这个函数放到宏任务队列的末尾,必须等当前执行栈清空、微任务队列清空之后才会轮到它。2018年的时候很多人对微任务的理解还停留在"Promise比setTimeout快"的模糊层面,没有形成"执行栈 -> 微任务 -> 宏任务"这样的完整心智模型。
如果复习时间有限,我建议优先把这个执行顺序模型彻底搞懂,因为它是JavaScript异步编程的基石,一旦理解到位,很多看似复杂的异步题目都能迎刃而解。
3.2 this指向的三种情况
this指向是JS笔试题里最常见的命题角度,B卷也不意外。它一般会通过几种不同的调用方式来混淆你:
- 普通函数调用:this指向全局对象(浏览器里是window)
- 对象方法调用:this指向该对象
- 构造函数调用:this指向新创建的实例
- 箭头函数:this继承外部作用域
B卷里的题目用了这样一个套路:先定义一个对象,对象里有一个方法,方法内部又定义了一个普通函数,普通函数内部访问this。很多人看到"对象方法里的函数"就默认this指向对象,但实际上普通函数有自己独立的this,在非严格模式下会指向window。
这类题还有一个进阶版本:把方法赋值给一个变量再调用,此时this会丢失绑定。原因就在于,函数本身的this是在调用时确定的,你把它从对象里抽出来,调用方式就变成了普通函数调用,this自然就变了。
如果想彻底掌握this,我建议自己推演一遍"调用位置决定this"这句话的含义。JavaScript的this不是定义时确定的,而是运行时由调用方式决定的。唯一例外是箭头函数,它不绑定this,而是继承外层作用域的this。把这个底层逻辑理顺了,不管题目怎么变,你都能推理出正确答案。
3.3 原型链与继承
原型链在2018年的笔试题里出镜率极高,B卷里有两道题直接涉及这个主题。一道是判断实例属性和原型属性的关系,另一道是要求用代码实现一种继承方式。
判断属性归属的题目,核心是理解hasOwnProperty和in操作符的区别。in操作符会沿着原型链查找,而hasOwnProperty只看对象自身。很多人平时开发用Object.keys()比较多,对这两个的区分就不够敏感。
实现继承的题目,我建议掌握至少三种方式,并能说出各自优劣:
// 方式一:原型链继承 function Parent() {} function Child() {} Child.prototype = new Parent(); // 方式二:组合继承 function Parent(name) { this.name = name; } function Child(name, age) { Parent.call(this, name); this.age = age; } Child.prototype = new Parent(); Child.prototype.constructor = Child; // 方式三:ES6 class class Parent {} class Child extends Parent { constructor() { super(); } }答题时如果能顺带说明ES6的class本质上是原型链的语法糖,以及组合继承为什么能解决原型链继承的属性共享问题,分数会明显不一样。
3.4 闭包与作用域
闭包是另一个必考主题。B卷里的考察方式比较直接,给你一段循环加setTimeout的代码,问输出什么。这种题已经是经典的"闭包陷阱"了:
for (var i = 0; i < 5; i++) { setTimeout(() => { console.log(i); }, 100); }输出是5个5,而不是0、1、2、3、4。原因是var声明的i是函数作用域,循环结束后i变成了5,而setTimeout的回调在循环结束后才执行,读取到的就是最终的5。
解决方案有三种:
- 用let声明i,形成块级作用域
- 用IIFE(立即执行函数)包裹,把i作为参数传进去
- 将setTimeout的参数形式
setTimeout(callback, delay, param)利用起来
这道题考查的其实不只是闭包,还有var与let的区别。现在ES6已经很普及了,但如果笔试题里为了考察理解深度,特意用var来写,你还是要能解释清楚为什么结果是这样。
4. 网络、浏览器与安全的隐藏基本面
前端笔试如果只看CSS和JS就错了,B卷里还有一批题目分布在网络协议、浏览器渲染和安全问题上。这部分虽然分值占比不高,但往往是高分选手与普通选手拉开差距的地方。因为大部分前端学习者会忽略这些"跟写页面关系不太大"的知识。
4.1 输入URL到页面展示的完整过程
这道题几乎是一线互联网公司笔试题的标配,B卷也没有跳过。它考察的链路非常长,可以从DNS解析一直讲到DOM渲染,任何一个环节有知识盲区都会露馅。
完整的过程大致是:
- DNS解析:把域名解析成IP地址
- 建立TCP连接:三次握手
- 发送HTTP请求:构造并发送请求头、请求体
- 服务器处理并返回响应
- 浏览器解析HTML:构建DOM树
- 解析CSS:构建CSSOM树
- 合并生成渲染树
- 布局与绘制
这个过程中隐藏的考点非常多。比如DNS解析的流程(浏览器缓存、系统缓存、路由器缓存、根域名服务器);TCP三次握手的每个步骤在干什么;HTTP请求行、请求头、请求体各自包含什么;DOM树和CSSOM树为什么要分别构建;渲染树和DOM树的区别是什么(display:none的元素不会出现在渲染树上)等等。
如果能把完整过程讲清楚,并且中间穿插一些自己实际遇到的问题(比如DNS缓存导致的页面异常、渲染阻塞的表现),就能让面试官看到你并不是在背答案,而是真的遇到过这些问题。这也是为什么我在复盘这套题的时候建议别人,不要只背大框架,每个环节至少准备一个真实的坑。
从某种程度上说,这道题是前端知识体系的试金石。它没有固定的标准答案长度,但回答的深度和细节密度,能直接反映你知识体系的完整程度。
4.2 浏览器缓存机制
B卷里有一道简答题问浏览器缓存的分类和区别。这个知识点在实际开发中极其重要,尤其是做前端性能优化的时候,缓存的命中策略直接决定了页面加载速度。
完整回答应该覆盖:
- 强缓存与协商缓存
- 强缓存的实现方式:Expires和Cache-Control
- 协商缓存的实现方式:Last-Modified/If-Modified-Since和ETag/If-None-Match
- 两者的优先顺序:Cache-Control优先于Expires;ETag优先于Last-Modified
有一点值得注意:Expires是HTTP/1.0时代的产物,它指定的是一个绝对时间,一旦客户端时间与服务器时间不一致就很容易失效。Cache-Control的max-age是相对时间,从请求发出时开始计算,不会受到客户端和服务器时间差的影响。这也是为什么现在普遍推荐使用Cache-Control。
2018年时候讨论这些知识点,还需要额外考虑一个场景:使用了强缓存之后,如果前端发布了新版本,怎么让用户尽快看到更新?常规操作是给静态资源文件名加hash,版本更新后文件名变化,缓存自然失效。这个思路放到今天依然是主流做法,但在笔试题里未必会展开问,知道就能加分。
4.3 跨域问题的根源与解法
B卷里有一道题是这样的:什么是跨域?如何解决跨域问题?
跨域问题的根源是浏览器的同源策略。所谓同源,是指协议、域名、端口三者完全一致。任何一者有差异,都会被浏览器视为不同源,从而限制跨源请求的读取。
常用的跨域解决方案包括:
- JSONP:利用script标签不受同源策略限制的特性,动态创建script标签,通过查询参数传递回调函数名,服务器返回一段调用该回调函数的JS代码。缺点是只支持GET请求。
- CORS:服务器在响应头中设置Access-Control-Allow-Origin,浏览器在发起请求时会自动校验。分为简单请求和预检请求两种情况。
- 代理转发:在同源的服务器端转发请求,规避浏览器的同源限制。
这道题如果往深了问,还会涉及"简单请求"和"预检请求"的区别。简单请求需要满足几个条件,比如使用GET、HEAD、POST这三种请求方法之一,并且请求头只包含一些安全的字段。只要不满足这些条件,浏览器就会先发送一个OPTIONS请求,询问服务器是否允许跨域,然后再发真正的请求。这里如果答不好,也会暴露对HTTP协议理解不深的问题。
4.4 XSS与CSRF:安全基础题不能丢分
B卷里有两道安全相关的题,一道是XSS,一道是CSRF。这俩在2018年前端岗位的需求中已经频繁出现,属于基本安全素养。
XSS(跨站脚本攻击)的核心是:攻击者注入恶意脚本到页面中,然后脚本在受害者的浏览器中执行,窃取cookie、劫持会话、篡改页面等。常见防御手段是输出转义,以及对用户输入进行过滤和校验。
CSRF(跨站请求伪造)的核心是:攻击者诱导用户访问第三方页面,利用用户已登录的身份,向目标站点发送伪造请求。常见防御手段包括:使用POST请求、校验Referer、添加CSRF Token、设置SameSite Cookie属性。
两者容易混淆。简单地说,XSS攻击的是用户对网站的信任,CSRF攻击的是网站对用户的信任。B卷这道题如果能在答案里说清楚这句话,就会显得理解很透彻。
5. 编程题与读代码题的实战应对
B卷最后一部分是编程题,这类题目在所有公司的笔试中都是决定能否进入面试的关键。客观题只要复习到位就能拿分,编程题却要在有限时间内写出可运行、符合要求的代码,心态稍微不稳就可能满盘皆输。
5.1 手写数组去重与排序
数组去重几乎是前端笔试的保留节目,B卷里也不例外。这道题的开放度很高,因为它有太多解法,每种解法背后的知识储备不同,考察效果也不同。
基础解法是双重循环或indexOf判断。进阶解法是使用Set:
const result = [...new Set(arr)];再进阶一点,还可以用filter配合indexOf:
const result = arr.filter((item, index) => arr.indexOf(item) === index);但如果纯粹靠set一行代码解决,只能说明你知道ES6新特性,并不能证明你对数组方法掌握得好。我的建议是,把每种解法都写一遍,然后想清楚:每种解法的时间复杂度是多少?对于引用类型是否适用?
如果题目再加一个排序的要求,那就要想好排序的稳定性问题。JavaScript的Array.prototype.sort在不同浏览器中的实现不同,V8在早期版本中排序算法是不稳定的,后来才改成稳定的。笔试作答时,一般不需要手动实现快排,但至少要能说出sort的默认排序规则是按字符串Unicode码点排序的,所以数字排序必须要传比较函数。
5.2 深拷贝的实现
深拷贝也是高频考点。B卷里要求写一个深拷贝函数,并至少处理对象和数组两种情形。
最简单的实现是借助JSON:
const clone = JSON.parse(JSON.stringify(obj));但JSON方案有明显的坑:函数、undefined、Symbol、循环引用都会被忽略或报错。所以笔试中只写JSON方案是不够的,面试官会进一步追问如何解决这些问题。
一个相对完整的递归深拷贝可以这样写:
function deepClone(obj, map = new WeakMap()) { if (typeof obj !== 'object' || obj === null) { return obj; } if (map.has(obj)) { return map.get(obj); } const clone = Array.isArray(obj) ? [] : {}; map.set(obj, clone); for (let key in obj) { if (obj.hasOwnProperty(key)) { clone[key] = deepClone(obj[key], map); } } return clone; }代码里面最容易被问到的点就是:为什么要使用WeakMap来存储已拷贝对象?核心原因是解决循环引用的问题。普通对象的key只能是字符串或Symbol,而WeakMap可以用对象作为key,并且WeakMap对key的引用是弱引用,不会阻止垃圾回收。如果深拷贝的对象是循环引用的,不用map记录,递归会无限循环下去,导致栈溢出。
如果你能在深拷贝的考察中主动提到"循环引用会栈溢出,我用WeakMap记录已拷贝对象来解决",这会给阅卷人留下很好的印象。
5.3 防抖与节流的实现
防抖和节流是前端高频手写题,B卷里选的是防抖。题目要求实现一个函数,让它在事件触发后延迟执行,并且在延迟期间内如果再次触发,则重新计时。
一个基本的防抖实现如下:
function debounce(fn, delay) { let timer = null; return function(...args) { if (timer) { clearTimeout(timer); } timer = setTimeout(() => { fn.apply(this, args); }, delay); }; }要注意的关键点是:返回的函数内部必须使用fn.apply(this, args),这样才能确保事件处理函数里的this指向正确。很多人写防抖时只传了args,却把this丢掉,虽然在前端框架封装好的场景里能用,但在原生事件绑定中就会出问题。
如果笔试时间充裕,我建议顺手把节流也写一遍。节流的实现方式有两种:时间戳版本和定时器版本。时间戳版本的特点是立即执行,定时器版本的特点是延迟执行。两者各有适用场景,能说出这个区别,比单单写出代码要好得多。
5.4 读代码题的得分技巧
B卷里还有一些给代码段让你判断输出结果的题。这类题的难点不在于知识点本身,而在于题目设计者会特意设置一些"看起来对但实际上不对"的陷阱。
我做这类题有一个固定的应对策略:先确定作用域边界,再确定调用形式,最后追踪执行顺序。作用域边界用来确定变量查找路径;调用形式用来确定this指向;执行顺序用来确定异步回调和事件循环中的谁先谁后。把这三件事按顺序分析完,大部分读代码题都能在纸上画出完整的推演过程。
有一个常见的错误是"猜测性作答"。遇到没把握的题目,很多人的第一反应是凭直觉猜一个答案,然后跳过去做下一题。但笔试的判分机制通常是答错倒扣分或者答错不得分,猜测的代价并不低。更合理的做法是在草稿纸上把能确定的执行过程先写出来,每一步都推一遍,至少能把两个明显错误的选项排除掉。前端的读代码题本质上都是可以推演出来的,不需要猜。
6. 从这套题反推备考策略和踩坑教训
这套题真正有价值的地方,并不仅仅在于题目本身,而在于它反映了一个公司在校招笔试环节对候选人的期望模型。通过这套题的考察范围,其实能看到前端工程师能力模型的几个关键维度。
6.1 基础知识的"宽"和"深"同样重要
前端这个行业变化极快。2018年的时候,Vue还是2.x,React还停留在16.x时代,Hooks还没有全面普及。如果你在那时候把精力全部放在特定框架的API上,到今天就几乎没有价值了。但基础知识不一样,事件循环、原型链、闭包、盒模型、浏览器缓存、HTTP协议,这些内容在今天依然是前端面试的高频考点,甚至在AI辅助编程的时代,这些基础决定了你能否正确理解和排查AI生成代码里的bug。
从备考角度说,我建议把所有基础知识按照"JavaScript语言、CSS与布局、浏览器与网络、安全与性能"四个维度列一个知识清单,然后逐个检查自己能否在不看资料的情况下讲清楚每一个知识点。讲不清楚的,就是备考期间需要重点补的盲区。
6.2 手写代码题的刻意练习要限定时间
很多人在准备笔试的时候有一个误区:把代码题在编辑器里写一遍,跑通就算过了。但真正的笔试环境是有限时的,而且很多时候没有代码提示、没有自动补全、甚至连调试工具都没有。如果在平时练习里习惯了借助IDE的提示和调试器,到了笔试场上就会很不适应。
我的建议是:备考期间每天花一到两个小时,打开一个纯文本编辑器,把常见的手写题——数组去重、深拷贝、防抖节流、Promise.all、柯里化、bind/apply/call实现等——各写三到五遍,写完直接看一遍逻辑,再把Timer设短一些,模拟真实考试的紧迫感。
刚开始可能会发现自己离开IDE就不会写代码了,键盘上敲一行删一行。这非常正常,坚持一个礼拜左右,速度和准确率都会明显提升。这个训练方式我一直推荐给身边准备校招的人,效果比盲目刷几百道选择题要好得多。
6.3 读题要慢,写题要快
B卷里有一道题让我印象特别深:它要求"用两种方式实现同一个需求",但很多人只写了一种就跳到下一题了。不是因为他们不会第二种,而是因为读题的时候没看清楚"两种"这个关键词。
笔试中的时间压力确实很大,但读题花掉的三十秒绝对是值得的。我的原则是:第一遍读题只做一件事,标注题目中的所有限制条件。比如"不得使用xxx""尽可能多""写出完整代码""至少两种方案"。把这些关键词圈出来再开始作答,看起来慢,实际上避免了因为理解偏差造成的返工。
6.4 踩过的坑:没注意题目运行环境导致丢分
最后聊一个真实的教训。有一次我模拟做B卷,有一道程序运行结果的题目,代码里用了window对象,而题目环境标注的是Node.js。我在草稿纸上按照浏览器环境推演,结果答错了。后来复盘才发现,题目开头其实写了"在Node.js环境下执行以下代码"。
浏览器全局对象是window,Node.js全局对象是global,如果没有显式声明变量就直接赋值,在浏览器中会成为window的属性,但在Node.js中则不会挂载到global上。这种环境差异会直接影响代码执行结果的判断。
所以正式答题前,一定要先确认题目代码的运行环境。前端笔试题有时候不一定都是浏览器环境,有些公司喜欢把Node.js和浏览器混在一起出题,就是为了测试你是否能区分这两套运行模型。B卷里虽然没有特别难的环境题,但这个意识一定要有。
复习这套题的过程,实际上是把前端基础能力体系重新梳理一遍的过程。把每一个考点背后的原理搞透,不仅是为了通过笔试,更是为后续面试环节和技术成长打基础。前端这行,基础扎实的人走到哪里都不会吃亏。