2024年,我们该如何学习 WEB 前端开发?(1)

这一份代码是 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 元素,添加事件,然后通过 class 和 style 对页面进行动态地变更,以完成对用户行为的响应;

**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 代码用

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

  • 打包工具:webpack、rollup

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

 工程化开发语言

相信很多同学都听说过 JavaScript 诞生之初的一些轶事,比如根本没有特别多的严谨思考,或者在非常多的场景中十分地晦涩,比如隐性转换等。

有人认为 JavaScript 能发展到如今的地位跟它的这种“灵活度”或者“松散度”有关联,虽然在某种程度上确实因为这种特性造成的 JavaScript 学习门槛比较低而间接导致。但就如我上面所说,当项目规模和人员规模不断发展乃至膨胀过后,这些特性会逐渐表现出来非常糟糕的体验:

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

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

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

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

  • Java 系:Scala.js、ClojureScript

  • Go 系:GopherJS

  • Microsoft:TypeScript

  • Facebook:Flow、Reason

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

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

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

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

 工程化通用组件

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

  • React:Ant Design、Fusion Design

  • Vue:Element UI、iView、Ant Design of Vue

逻辑抽象能力



随着我对 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]) break } } else if (state.raceCount[0][race] < output && arr.length === 1) { // Last condition arr.pop() } }

return arr }}

export default { beastBuff: generateBuff(‘beast’, [ [2, [2, 3], 8], [4, [4, 5], 9], [6, [6], 10], [2] ]),

caveclanBuff: generateBuff(‘caveclan’, [ [2, [2, 3], 11], [4, [4], 12], [2] ]), // …}

原本代码里面通过 hard code 实现的判断逻辑,通过观察其中的共同点,并思考能否通转换为可抽象部分,这同样也是一名优秀的工程师所必须具备的能力。

Be D.R.Y.! (Don’t repeat yourself)

更高层次的思考能力



随着我对不同业务、不同场景和不同代码难度的不断探索和研究,我发现在前端领域乃至整个编程领域里,不同的框架和架构层出不穷地发展,其实在根本上就是各种实际业务场景在寻找更合适的 Better Practice(更好实践)。就如前面的所说的那样,不同的框架作者在开发的时候会采取不同的代码结构甚至代码哲学,这些不同的思维角度可能在框架的源码中并不会直接表现出来。但我不会说研读源码完全没有用!因为研读源码最起码可以学习其中的一些 trick 或者代码习惯。

但更重要的是理解从 API、系统架构上进行思考,因为只有多思考了,你才能逐渐变得比其他人更加对不同的技术游刃有余。

EOF



这一个流程并不是严谨的学习路线,更多的是我个人的一些经验总结。当然除了我所提到的学习知识点以外,还有很多不同的分支对应着不同的实际业务和场景,比如配合 Electron 开发桌面端应用、配合 React Native/Flutter 开发移动端应用、配合 Node.js/QuickJS/FibJS 开发嵌入式应用、配合 TensorFlow.js 开发适用于前端甚至适用于边缘计算的机器学习应用、配合 WebAssembly 将 Web 应用的使用体验提升到接近原生应用的境界……

关于 JavaScript 有一个很有名的预言:

凡是能用 JavaScript 重写的,终将会使用 JavaScript 重写

无论这句话会不会最终完全实现,但目前我们已经能看到很多应用逐渐通过 Web 应用的形式云端化,比如 Photoshop、音视频编辑软件、代码编辑器甚至是大型游戏等等原本我们完全没想到可以运行在浏览器中。

前端开发困难吗?不困难、门槛相对比较低。简单吗?不简单,通过相信看到这里的你也已经有所体会了。当然实际要如何选择路线和方向,还是你自己所遇到的经历和机遇来决定的。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

最后:

总结来说,面试成功=基础知识+项目经验+表达技巧+运气。我们无法控制运气,但是我们可以在别的地方花更多时间,每个环节都提前做好准备。

面试一方面是为了找到工作,升职加薪,另一方面也是对于自我能力的考察。能够面试成功不仅仅是来自面试前的临时抱佛脚,更重要的是在平时学习和工作中不断积累和坚持,把每个知识点、每一次项目开发、每次遇到的难点知识,做好积累,实践和总结。

点击这里领取Web前端开发经典面试题

正体系化!**

[外链图片转存中…(img-5fO1D4kS-1713438263905)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

[外链图片转存中…(img-2mzrDBZa-1713438263906)]

最后:

总结来说,面试成功=基础知识+项目经验+表达技巧+运气。我们无法控制运气,但是我们可以在别的地方花更多时间,每个环节都提前做好准备。

面试一方面是为了找到工作,升职加薪,另一方面也是对于自我能力的考察。能够面试成功不仅仅是来自面试前的临时抱佛脚,更重要的是在平时学习和工作中不断积累和坚持,把每个知识点、每一次项目开发、每次遇到的难点知识,做好积累,实践和总结。

点击这里领取Web前端开发经典面试题

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值