2024年前端最全让你见识一下什么叫最完整、最系统的前端学习路线,2024年前端面试心得

Vue 面试题

1.Vue 双向绑定原理
2.描述下 vue 从初始化页面–修改数据–刷新页面 UI 的过程?
3.你是如何理解 Vue 的响应式系统的?
4.虚拟 DOM 实现原理
5.既然 Vue 通过数据劫持可以精准探测数据变化,为什么还需要虚拟 DOM 进行 diff 检测差异?
6.Vue 中 key 值的作用?
7.Vue 的生命周期
8.Vue 组件间通信有哪些方式?
9.watch、methods 和 computed 的区别?
10.vue 中怎么重置 data?
11.组件中写 name 选项有什么作用?
12.vue-router 有哪些钩子函数?
13.route 和 router 的区别是什么?
14.说一下 Vue 和 React 的认识,做一个简单的对比
15.Vue 的 nextTick 的原理是什么?
16.Vuex 有哪几种属性?
17.vue 首屏加载优化
18.Vue 3.0 有没有过了解?
19.vue-cli 替我们做了哪些工作?

如果你觉得对你有帮助,可以戳这里获取:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

三、接触 Node.js


当我正在愉快地设计着 WordPress 的自定义主题时,偶然间我在某前端网站上了解到了一个新的技术 —— Node.js。与它的相遇改变了我以后的学习路径,影响至今。

2009 年 Ryan Dahl 发布了一个基于 Chrome JavaScript V8 引擎开发的程序运行环境 Node.js,它允许开发者在除了浏览器以外的地方运行 JavaScript 语言,并且提供一些标准库允许 JavaScript 脚本启动进行启动一个 HTTP 服务端应用这种以前在浏览器无法完成的事情。

var http = require(‘http’);

http.createServer(function (req, res) {

res.writeHead(200, {‘Content-Type’: ‘text/plain’});

res.end(‘Hello World\n’);

}).listen(8124, “127.0.0.1”);

console.log(‘Server running at http://127.0.0.1:8124/’);

这一份代码是 2010 年写在 Node.js 官网的一段实例代码,机缘巧合之下我被这么一段简单的代码深深地吸引住了,虽然当时安装它仍需要从 GitHub 上克隆整个项目代码到本地并依次运行以下指令:

$ ./configure

$ make

$ make install

这一次编译就得花上至少十分钟,但完成安装后运行上面的一段代码,并在浏览器中打开 http://127.0.0.1:8124/,然后在浏览器上看到 Hello World 字样时仿佛新世界的门打开了。因为当时我所接触过的服务端程序只有 PHP,而 PHP 本质上就是一个模板引擎,它并不能很直观地处理请求本身而是借助 CGI 进行响应。能做更多的事情,这件事情对刚学习编程不久的新手来说是具有很大诱惑力的。

从这里开始,Node.js 配合 npm 便开始了长达 10 年的快速发展。从纯服务端应用开发,到开发工具、工程工具,再到如今的 FaaS(Function as a Service,Serverless)开发方式。Node.js 已经成为 Web 工程师不可或缺的一项技能,不管是用来开发服务端应用还是开发工具类应用,甚至是使用 Electron 开发桌面端应用还是配合 React Native 开发移动端 App,Node.js 能让前端工程师了解更多系统级别的概念,如网络、I/O、内存、文件系统等等,这些很多都是原本在浏览器端上看不到的。而学习这些知识对你理解前端开发背后的一些原理有非常好的价值,就跟学习算法一样。

结论:请学习 Node.js 和其中涉及到的一些基本计算机原理。

四、框架时代


当我在做 WordPress 主题的时候,绝大部分的主题开发者都会在前端做一些简单的效果,甚至有甚者会通过 JavaScript 实现一些原本只能通过后端来完成的事情,比如文章列表、文章内容的加载和渲染。

而当年这些主题开发者基本上都会使用 jQuery 来进行这些 JavaScript 的操作,因为纯手写 JavaScript 在当时来说非常的繁琐(ES4时代,很多现在被广泛使用的原生 API 都仍未具备)所以当时 jQuery 就是大家的首选方案。

从非常早的 PrototypeJS、后来的 jQuery、进入 MVC 时代的 Backbone,AngularJS 开启 MVVM 模式,React 引入 FP 的概念,Vue 成功开启了渐进式开发体验的道路。一路下来一地的鸡毛,被各路人马诟病前端领域一个月开发一个新框架,“学不动了”。然而作为一个也写过框架、写过工具类库的开发者,我很喜欢用一个经常用于泛科技领域的例子来类比前端领域:科技的终极目标,就是让人民感觉不到科技。

jQuery 时代,前端开发者使用 JavaScript 的模式是从页面中获取 DOM 元素,添加事件,然后通过 classstyle 对页面进行动态地变更,以完成对用户行为的响应;

Backbone 时代,原本用在桌面端软件开发中的 MVC 模式被引入到了前端开发中,前端开发者们发现 Web 开发的复杂度已经需要用这些更成熟的开发模式进行管理了;

AngularJS 时代,从这里开始 Google 把数据双向绑定模式带到前端开发中,将原本需要通过 JavaScript 控制 DOM 元素这一繁琐的操作变成了只需要关心 Model 层需要改动什么内容即可。

Vue 则将这种模式的开发成本降低到了一种相当可观的程度,让很多新手开发者也能很简单地入手这种便捷的开发模式。

React 时代,Facebook 的科学家们把函数式编程的思想引入到前端开发中,注重的是数据链路的可跟踪、可回溯、可管理,让整个数据链路是尽可能以单链路流转。

虽然前端领域常被说“一个月一个新框架”,但实际上每一个框架在迭代的过程中都是解决了它们所在业务场景的实际需求的,并不是“拍脑袋”地想要把每一个技术细节做出一个 break change。

而目前我目前推荐的学习的框架是 React 和 Vue:

  • 同样都是目前最流行的框架之一,而且可以预见未来 3~5 年内都是能满足找工作的需求的;

  • React:引入函数式编程(Functional Programming)的概念,使得写代码的思路更加严谨,更具有可维护性和逻辑可导性;

  • Vue:将 MVVM 模式变得非常简单易于入手,把 Progressive JavaScript Framework 的定位实践得非常到位。且如今 Vue 3.0 的 Composition API 更是在某种程度上将 Hooks 的玩法实现得比 React Hooks 更优;

结论:请不要害怕学习!不要惧怕新技术!

五、工程之路


虽然我在接触了框架和 Node.js 之后,发现 JavaScript 除了能实现一般只用于展示内容和呈现简单交互以外还能做更多的事情。但本质上还是围绕着多个页面进行页面上 DOM 元素的控制,而直到我打开了 Google 的一些网站时,我才发现原来网站除了能叫页面以外,还能称之为“应用”。自从 Google 上线了一个完全不需要刷新页面就能完成所有事情而且体验很不错的 GMail 之后,我们发现网页原来也是可以承载那么复杂的逻辑和应用场景的。大家的热情异常地高涨,想着能不能让自己所负责的项目也有这么厉害高级的样子。但随着项目不断地复杂,代码规模也变得非常难以管理,而这个时候就需要工程化的引入。

工程化协作

对于企业来说除了研发效率要足够高以外,研发链路的安全、合规也是同样重要的。什么叫安全合规?可管理的代码版本、可控制的发布流程、可管控的灰度机制,都是大厂用于保证项目流程稳定进行的必要工具。有很多初学者或者还没有大公司经验的同学在写项目时都是单打独斗的,但更多的一线项目都需要至少 2~3 个甚至更多的人员一同参与开发的。而这种时候,因为每个人的水平和开发习惯都是不一致的,而这些不一致就直接导致整体研发效率和项目进度受到极大的影响。所以就需要一种能够让大家在一个水平线上进行开发的模式,工程化需求便应运而生。

  • 版本控制

  • Git:GitHub、GitLab、Coding……

  • SVN:BitBucket、Google Code……

  • 代码样式检查工具 JavaScript/TypeScript:ESLint

  • 测试工具

  • 单元测试:Karma、Jest、Mocha……

  • 持续集成:CI

  • ……

工程化开发工具

从直接将 JavaScript 代码用 <script> 标签,到需要将 jQuery 文件和主要程序文件分别引入,再到 Node.js 出现后使用 npm 进行依赖库管理并使用 webpack 进行打包和压缩。工程类工具的发展见证着前端工程近十年的发展历史,对目前我们所常用的工程工具有更好的了解和实践,绝对是通往优秀路上不可或缺的一步。

  • 依赖包管理工具:npm、yarn

  • 打包工具:webpack、rollup

  • 脚手架工具:create-react-app……

工程化开发语言

相信很多同学都听说过 JavaScript 诞生之初的一些轶事,比如根本没有特别多的严谨思考,或者在非常多的场景中十分地晦涩,比如隐性转换等。有人认为 JavaScript 能发展到如今的地位跟它的这种“灵活度”或者“松散度”有关联,虽然在某种程度上确实因为这种特性造成的 JavaScript 学习门槛比较低而间接导致。但就如我上面所说,当项目规模和人员规模不断发展乃至膨胀过后,这些特性会逐渐表现出来非常糟糕的体验:

  1. 团队之间因为没有良好的技术文档沉淀,信息不对等的情况直接导致代码在没有良好的单元测试时出现逻辑冲突;

  2. 第三方依赖库的 API 在设计上大量使用了 JavaScript 松散的特性,导致使用方在引用时频繁出现“迷惑”的状态;

  3. 当需要使用 JavaScript 与其他语言(特别是强类型语言)进行交互时,JS 过于松散的习惯会让对接方感到非常迷惑,对于双方的实际接入成本会比前期预估的大得多;

为了解决这种情况,来自不同编程领域的大牛们都纷纷开始想办法,于是乎便诞生了非常多的“轮子”:

目前 TypeScript 已经影响了前端乃至整个 Web 领域的开发生态,TypeScript 之父 Anders Hejlsberg 创造过 Turbo Pascal、Delphi、C# 等在整个计算机科学领域都举足轻重的语言,而 TypeScript 又再次创造出翻天覆地的变化:

  • 强类型的引入能让我们在写代码的时候从值优先的思维转变成类型优先

  • 强类型的引入能帮助开发工具(IDE 等)更好地为开发者提供便利性能力,如智能补全、类型检测、编译时检查等等;

  • TypeScript 可以让 JavaScript 更好地与其他语言进行交互,甚至转换为其他语言;

工程化通用组件

当需求不断变多后,“爱偷懒”的工程师们就会把经常用到的内容进行抽象,比如从很早以前就有的 ExtJS、Twitter 工程师发布的 Bootstrap 再到今天的 Ant Design、Element UI 等,都帮助我们更快更好更稳定地完成一些通用页面能力的开发。

六、逻辑抽象能力


随着我对 JavaScript 应用的编写经验不断增加,我所尝试的技术和场景也在不断地变得更加复杂。而当逻辑代码变得越来越复杂时我也渐渐发现一个新的问题,很多时候我所编写的逻辑代码是相似的,但相似之余其中的一些细节不尽相同,而这些代码往往是后期维护成本最高的。这就让我感到十分困惑,如何让我的代码写起来没有那么繁琐的同时,又不丢失原本代码的应有逻辑呢?这就让我想起了之前学习的框架,它们的实现原理不就是把原本我们写得非常繁琐的逻辑代码进行压缩,让我们写起来更加简洁直观吗?

这是我曾经面试过的一位校招候选人写的代码,其背景是用于快速判断自走棋类游戏中不同的增益能力(Buff)的成立状态。但显然这样的代码在实际开发中是绝对不允许存在的:

  1. 代码逻辑过于冗余;

  2. 一旦通用判断逻辑出现变动,需要每一个都进行手动维护;

  3. 没有良好的可维护性;

所以我便提出如何让这些代码写得更加“优雅”和利于维护。

export default {

beastBuff: (state) => {

let arr = [];

if (state.raceCount[0][‘beast’] == 2 || state.raceCount[0][‘beast’] == 3) {

console.log(you got 2 beast)

arr.push(state.racebuffdata[8])

} else if (state.raceCount[0][‘beast’] == 4 || state.raceCount[0][‘beast’] == 5) {

console.log(you got 4 beast)

arr.pop()

arr.push(state.racebuffdata[9])

} else if (state.raceCount[0][‘beast’] == 6) {

console.log(you got 6 beast)

arr.pop()

arr.push(state.racebuffdata[10])

} else if (state.raceCount[0][‘beast’] < 2 && arr.length == 1) {

arr.pop()

}

return arr;

},

caveclanBuff: (state) => {

let arr = [];

if (state.raceCount[1][‘caveclan’] == 2 || state.raceCount[1][‘caveclan’] == 3) {

console.log(you got 2 caveclan)

arr.push(state.racebuffdata[11])

} else if (state.raceCount[1][‘caveclan’] == 4) {

console.log(you got 4 caveclan)

arr.pop()

arr.push(state.racebuffdata[12])

} else if (state.raceCount[1][‘caveclan’] < 2 && arr.length == 1) {

arr.pop()

}

return arr;

},

demonBuff: (state) => {

let arr = [];

if (state.raceCount[2][‘demon’] == 1) {

console.log(you got 1 demon)

arr.push(state.racebuffdata[5])

} else if (state.raceCount[2][‘demon’] < 1 && arr.length == 1) {

arr.pop()

}

return arr;

}

// …

}

我们不难发现这几个 xxxBuff 函数中的逻辑都非常接近,但也各有不同。那么如何能将这段代码进行优化和抽象呢?我当时给 TA 提出了一份示例代码:

const beastConfig = [

[2, [2, 3], 8],

[4, [4, 5], 9],

[6, [6], 10],

[2]

]

这份代码中的每一个数字在上面的 beastBuff 函数中都可以一一找到,那么要怎么将它们复用到逻辑代码中,实现与原本的代码一样的功能呢?

我同样给他写了一份参考答案:

const generateBuff = (rate, configArr) => {

return state => {

const arr = []

for (const [ output, conditions, index ] of configArr) {

if (conditions && index) {

// Buff calculating

const isHit = conditions.some(condition => state.raceCount[0][race] == condition)

if (isHit) {

console.log(you got ${output} ${race})

arr.pop()

arr.push(state.racebuffdata[index])

最后

喜欢的话别忘了关注、点赞哦~

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

前端校招面试题精编解析大全

if (conditions && index) {

// Buff calculating

const isHit = conditions.some(condition => state.raceCount[0][race] == condition)

if (isHit) {

console.log(you got ${output} ${race})

arr.pop()

arr.push(state.racebuffdata[index])

最后

喜欢的话别忘了关注、点赞哦~

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

前端校招面试题精编解析大全

  • 28
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值