前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >落魄前端,整理给自己的前端知识体系复习大纲(下篇)

落魄前端,整理给自己的前端知识体系复习大纲(下篇)

原创
作者头像
用户8671053
修改2021-09-19 20:33:50
5320
修改2021-09-19 20:33:50
举报
文章被收录于专栏:码农的生活码农的生活

前言

首先,感谢一些同行们对上篇的肯定。

其次,文章标题为"大纲",只是笔者,整理给自己的一个复习大纲。

也许内容并不深入,因为文章的标题与定义就是大纲,并没指望一篇文章,可以教会提到的对应的知识点。无论哪个知识点,一个原型链最基础的东西,都可进行深挖,大神都可以扯上几万字,也未必能让所有人看懂,培训机构上万的学费,也未必敢说一句包你懂,何况笔者只是一个免费的大纲汇总呢?本文仅是大纲而已。大家哪个知识点不熟悉,应该学会自己查漏补缺,自己学习着去深入。

也许错别字,也许知识点有误,因为时间紧迫,精力有限,能力也有限,多多包涵,也欢迎您的指出,大家一起进步。

下篇,不像上篇,很多都是一个开放性的答案,也因个人时间原因,故只提供一个简介,或者第三方链接。

大纲

本章一共有两篇:

上篇主要为html,css,js,es6,浏览器等基础知识。

下篇主要为手写api,网络编程基础,设计模式基础,源码指引,框架复习指引等。

其中,该文为下篇,上篇链接为:juejin.im/post/686771…

三.巩固前端基建

本章重点,提供的知识点的归类,以及重点。具体的知识点不做多余的介绍。(如果对知识点不熟悉,建议重点突击补充一下。)

在职前端开发,如果你也想学习前端开发技术,可以加入我组建的前端学习交流裙:851 231 348

也可以关注我的微信公众号:【前端留学生】自己根据多年来的开发经验总结录制的

一套web前端精讲视频和学习方法,以及一些前端学习手册,前端面试题,端开发工具,

PDF文档书籍教程,无偿分享给大家。需要的话都可以自行来获取下载。

1

2

3

4

5

1)加深巩固篇

1.前端去重的方法有哪些?

看过一篇文章,里边有十二种,可以参考:segmentfault.com/a/119000001…

但是内容感觉很多重复,以及有点为重复而重复。笔者简单提及一下自己脑袋里可行的去重方法(关键字思维,代码太多了暂不提供):

1.利用Set,自带数组去重功能。也是ES6最实用的方法

2.利用Map,

3.for for splice/del

4.indexOf

5.sort

6.includes

7.hasOwnProperty

8.filte

9.递归

2.前端异步的方案有哪些?

1)Promise(可看上篇的解释)

2)generator(可看上篇的解释)

3)async/await

4)事件发布/监听模式(可看后续的设计模式,属于发布订阅模式,代表作EventBus)

async 和 await 相比直接使用 Promise 来说,优势在于处理 then 的调用链,能够更清晰准确的写出代码。缺点在于滥用 await 可能会导致性能问题,因为 await 会阻塞代码,也许之后的异步代码并不依赖于前者,但仍然需要等待前者完成,导致代码失去了并发性。

3.前端网络请求有哪些?

ajax, fetch, axios。

一句简单的语句来概括的话,ajax因为不支持promise给淘汰,从而有了fetch,然后fetch缺陷多,不支持对异常捕捉,不支持监听进度条,cookies不友好等等。所以,axios当今浪潮。

有兴趣了解,推荐:juejin.im/post/684490…

4.前端定时器有哪些?

异步编程当然少不了定时器了,常见的定时器函数有 setTimeout、setInterval、requestAnimationFrame。我们先来讲讲最常用的setTimeout,很多人认为 setTimeout 是延时多久,那就应该是多久后执行。

其实这个观点是错误的,因为 JS 是单线程执行的,如果前面的代码影响了性能,就会导致 setTimeout 不会按期执行。当然了,我们可以通过代码去修正 setTimeout,从而使定时器相对准确

首先 requestAnimationFrame 自带函数节流功能,基本可以保证在 16.6 毫秒内只执行一次(不掉帧的情况下),并且该函数的延时效果是精确的,没有其他定时器时间不准的问题,当然你也可以通过该函数来实现 setTimeout。

5.前端创建对象有哪几种方式?

该知识点只做汇总提示,不做具体分析。请各自查询资料查漏补缺。

1)var obj = new Object();

2)var obj = { name: ‘小明’ }

3)工厂模式

function createObj(name){

var o = new Object();

o.name = name;

o.fun = function(){

}

return o;

}

1

2

3

4

5

6

7

4)构造函数

function TestObj(name){

this.name = name;

}

1

2

3

5)原型创建

function TestObj(){}

Person.prototype.name = '小明';

};

1

2

3

6)构造函数 + 原型创建

7)class写法

6.前端的继承方式有哪些?

1.原型链继承

本质是重写了对象。

缺点:

1)对象实例共享所有继承的属性和方法

2)不能传递参数

2.构造函数继承

在子类构造函数的内部调用超类型构造函数。使用apply()和call() 方法

缺点:

1)函数复用性不高 ,每个实例都是重新实例化构造函数,不存在共享属性

2)只能继承实例上的属性,原型上的方法不可见

3.组合继承

本质:原型链 + 构造函数

Parent.call(this) new Parent()避免了上述的缺点,常用。

优点:可传参,不会与父类引用属性共享

缺点:继承父类函数的时候调用了父类构造函数,导致子类的原型上多了不需要的父类属性,存在内存上的浪费。

4.原型式继承

实现本质:object()函数对传入其中的对象执行了一次浅复制

5.寄生式继承

借用构造函数来继承属性,通过原型链的混成形式来继承方法

6.寄生组合

高效率只调用了一次构造函数,集寄生式继承和组合继承的优点于一身,是实现基于类型继承的最有效方式。

就是将父类的原型赋值给了子类,并且将构造函数设置为子类,这样既解决了无用的父类属性问题

Parent.call + Object.create()

详细可参考:juejin.im/post/684490…

7.前端代码的复用有哪几种方式?

该知识点只做汇总提示,不做具体分析。请各自查询资料查漏补缺。

1)函数封装

2)继承

3)复制extend

4)混入mixin

5)借用apply/call

2)手写api

此部分,废话不多说,直接给对应的代码!如果还有其他重要手写代码,留言笔者会考虑补充。

有源码不理解的朋友们,可自行查询资料,或留意关注笔者的解说: juejin.im/post/686940…

1.new

function createThis( proto ){

var obj = new Object;

obj.__proto__ = proto.prototype;

let [ constructor, ...args] = [ ...arguments ];

let result = constructor.apply( obj, args );

return typeof result === 'object' ? result : obj;

}

1

2

3

4

5

6

7

8

2.apply/call/bind

Function.prototype.wzApply = function (context) {

const thisContext = context ? context : windows;

thisContext.fn = this;

var result = null;

if (arguments[1]) {

result = thisContext.fn(...arguments[1]);

} else {

result = thisContext.fn();

}

delete thisContext.fn;

return result;

}

Function.prototype.wzCall = function (context) {

const thisContext = context ? context : windows;

thisContext.fn = this;

var result = null;

var args = [...arguments].slice(1)

if (args) {

result = thisContext.fn(...args);

} else {

result = thisContext.fn();

}

delete thisContext.fn;

return result;

}

Function.prototype.wzBind = function (context) {

var _this = this;

var arg = [...arguments].slice(1);

return function F(){

if( this instanceof F ){

return new _this(arg.concat(...arguments));

}

return _this.apply( context, arg.concat(...arguments) );

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

3.instanceOf

function _instanceof(A, B) {

var O = B.prototype;// 取B的显示原型

A = A.__proto__;// 取A的隐式原型

while (true) {

//Object.prototype.__proto__ === null

if (A === null)

return false;

if (O === A)

return true;

A = A.__proto__;

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

4.获取url参数

function getQuery( params ){

var query = window.location.search.substring(1);

var vars = query.split("&");

for (var i=0;i<vars.length;i++) {

var pair = vars[i].split("=");

if(pair[0] == params ){return pair[1];}

}

return(false);

}

1

2

3

4

5

6

7

8

9

10

5.模拟深拷贝

简版看笔者代码,如需要深入建议:www.kancloud.cn/ljw78947894…

function deepClone(initalObj, finalObj) {

var obj = finalObj || {};

for (var i in initalObj) {

var prop = initalObj[i]; // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况

if(prop === obj) {

continue;

}

if (typeof prop === 'object') {

obj[i] = (prop.constructor === Array) ? [] : {};

arguments.callee(prop, obj[i]);

} else {

obj[i] = prop;

}

}

return obj;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

6.防抖与节流

const debounce = (cb, wait = 500, immediate = true) => {

let timer = 0;

let context = null;

let param = null;

const later = () => setTimeout(() => {

timer = null;

if (!immediate) {

cb.apply(context, param);

context = null;

param = null;

}

}, wait);

return function (...args) {

if (!timer) {

timer = later();

if (immediate) {

cb.apply(this, args);

} else {

context = this;

param = args;

}

} else {

clearTimeout(timer);

time = later();

}

}

}

const throttle= (func, delay=500 ){

var timer = 0;

var startTime = Date.now();

return function( ...args ){

var context = this;

var currentTime = Date.now();//当前时间

var diffTime = currentTime - startTime; //时间差

clearTimeout(timer);

if( diffTime > delay){

func.apply( context, args);

startTime = Date.now();

}else{

timer = setTimeout( function(){

throttle( func, delay);

});

}

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

7.手写迭代器next

function createIterator(items) {

var i = 0;

return {

next: function() {

var done = (i >= items.length);

var value = !done ? items[i++] : undefined;

return {

done: done,

value: value

};

}

};

}

var iterator = createIterator([1, 2, 3]);

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

8.手写Object.freeze

function tFreeze(obj){

if(obj instanceof Object){

Object.seal(obj); // 封闭对象

for(let key in obj){

if(obj.hasOwnProperty(key)){

Object.defineProperty(obj,key,{

writable:false

})

myFreeze(obj[key]); //遍历

}

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

3)框架源码理解

源码是很多企业的考试重点,看不懂源码没关系,但是要明白源码大概是什么,大概的原理又是什么。此章节内容相对较多,笔者就不单独在本文解析。

笔者自身也处于探索或学习状态。如果你2到5年工作经验,想学习一下源码,可以参考一下笔者过去写的文章,那也是笔者的复习思路。

列的知识点,都是重点之重点。

如果你有一定的基础,或以及看过源码,或觉得网上还有更好的帖子,可以另从他处学习,不喜勿喷。

(笔者也是学习中写下的源码,有不足或者理解错误的地方,多多包涵与讨论)

1.vue源码

笔者mini版草文:juejin.im/post/684790…

2.react源码

笔者mini版草文:juejin.im/post/685457…

3.wepback源码

笔者mini版草文:juejin.im/post/685457…

4.vuex源码

笔者mini版草文:juejin.im/post/685705…

5.vue route源码

笔者mini版草文:juejin.im/post/686010…

6.diff源码

笔者mini版草文:juejin.im/post/686881…

7.promise源码

笔者mini版草文: juejin.im/post/686920…

8.react体系

react fiber,,react redux, react Hook等,笔者来不及学习或汇总,提供曾看到不错的文章:

React Fiber: juejin.im/post/685952…

React Hook:juejin.im/post/686774…

React redux: juejin.im/post/684490…

4)工具拓展篇

1.babel

概念部分拷贝:juejin.im/post/684490…

Babel是一个工具链,主要用于将ECMAScript 2015+版本代码向后兼容 Javascript 语法,以便可以运行到旧版本浏览器或其他环境中。

Babel 的三个主要处理步骤分别是: 解析(parse),转换(transform),生成(generate)。

解析

将代码解析成抽象语法树(AST),每个js引擎(比如Chrome浏览器中的V8引擎)都有自己的AST解析器,而Babel是通过Babylon实现的。在解析过程中有两个阶段:词法分析和语法分析,词法分析阶段把字符串形式的代码转换为令牌(tokens)流,令牌类似于AST中节点;而语法分析阶段则会把一个令牌流转换成 AST的形式,同时这个阶段会把令牌中的信息转换成AST的表述结构。

转换

在这个阶段,Babel接受得到AST并通过babel-traverse对其进行深度优先遍历,在此过程中对节点进行添加、更新及移除操作。这部分也是Babel插件介入工作的部分。

生成

将经过转换的AST通过babel-generator再转换成js代码,过程就是深度优先遍历整个AST,然后构建可以表示转换后代码的字符串。

babel编译原理

● babylon 将 ES6/ES7 代码解析成 AST

● babel-traverse 对 AST 进行遍历转译,得到新的 AST

● 新 AST 通过 babel-generator 转换成 ES5

babel/babel-polyfill

babel-polyfill:ES6的转码。IE的兼容

2.nignx

非专业人员,不过前端人员还是必要掌握一下前端如何部署。

简单的普及一下nignx,Nginx可见简单理解成,所开发高性能的 Web和 反向代理 服务器。

明白nigix如何实现正向代理,如何实现反向代理,如何完成负载均衡。本文不做重点介绍,有兴趣请移步:juejin.im/post/684490…

3.csr与ss

SSR(Server Side Rendering) :传统的渲染方式,由服务端把渲染的完整的页面吐给客户端。这样减少了一次客户端到服务端的一次http请求,加快相应速度,一般用于首屏的性能优化。

CSR(Client Side Rendering):是一种目前流行的渲染方式,它依赖的是运行在客户端的JS,用户首次发送请求只能得到小部分的指引性HTML代码。第二次请求将会请求更多包含HTML字符串的JS文件。

SSR优点:

1)有利于SEO的优化

2)首屏快

缺陷:

1)性能全都依赖于服务器

2)只能做静态,交互效果还是得用CSR,前端界面开发可操作性不高

3)开发条件受限,生命周期等。

反之,CSR 不利于SEO,首屏慢,但是交互效果好。

4.web Worke

想了解的朋友们移步:juejin.im/post/684490…

四.编程相关

这里为"编程相关",而不是"前端相关",因为这是无论哪个客户端的开发人员都必须掌握的基础。废话不多说,本文列举以前端挂钩的知识点。

1)设计模式篇

设计模式更是一种思维。设计模式一共23种,分创建型,结构,行为型。本文举几个,前端用到的几个设计模式,且是简单的描述一下。

如果对全面想要了解,可参考笔者曾经写过的一篇文章:juejin.im/post/684490…

此外,"徐小夕"这篇也是不错的。juejin.im/post/684490…

1.单例模式

一个极有可能重复出现的“实例”, 如果重复创建,是否消耗性能?如果借助第一次的实例,后续只是对该实例的重复使用,这样就达到了我们节省性能的目的。

可能服务端的朋友,知道什么是数据库链接池,这就是一个单例的经典模式,数据库连接池,与每次创建数据库连接,效率值将差异巨大。这就是单例模式的魅力。

我们前端的实践中,也经常可以借鉴这个思维。例如,登录弹出框,取消重新弹出时,再显示原来的弹出框,而不是重新创建。

var myLogin = function( fn ){

var result;

return function(){

return result || ( result = '<div>我是登陆框</div>' );

}

}

1

2

3

4

5

6

7

2.工厂模式

这里严格来说有两类设计模式,一个叫简单工厂,一个抽象工厂。

简单工厂模式叫做静态工厂方法模式,是由一个工厂对象决定创建出哪一种产品类的实例。例如富士康同时需要生产华为,苹果等手机,我们可用一个工厂的模型,生产人只要输入型号,就可以产出对应的手机。

抽象工厂,多一个抽象对象。抽象工厂是工厂方法模式的核心,所有创建对象的工厂类都必须实现该接口。 如上栗子,如果还需要手机颜色,内存大小,共同来确定一步手机,这就是抽象工厂。

抽象工厂,还需要使用户根据参数获得对应的类实例,避免了直接实例化类,降低了耦合性。

3.策略模式

简单点的理解,就是针对不同的状态,给出不同的算法或者结果。定义好策略组,根据不同的状态定义不同的策略。我们前端的实例,比如我们的form验证。

他的优点:

1、算法可以自由切换。

2、避免使用多重条件判断。

3、扩展性良好。

缺点:

1、策略类会增多。

2、所有策略类都需要对外暴露。

4.责任链模式

用来处理相关事务责任的一条执行链。例如前端JS 中的事件冒泡,一层一层往上传递。

优点:

1、降低耦合度。它将请求的发送者和接收者解耦。

2、简化了对象。使得对象不需要知道链的结构。

3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。

4、增加新的请求处理类很方便。

缺点:

不能保证请求一定被接收;代码调试时不太方便,可能会造成循环调用;

5.观察者模式(Vue必懂)

观察者模式(Vue双向绑定原理了解一下): 观察者(Observer)直接订阅(Subscribe)主题(Subject),而当主题被激活的时候,会触发(Fire Event)观察者里的事件。

发布订阅模式: 订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Topic),当发布者(Publisher)发布该事件(Publish topic)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。

发布订阅模式属于广义上的观察者模式。经过时间的沉淀,慢慢独立于观察者模式,成为另外一种不同的设计模式。

这篇写得挺好的:blog.csdn.net/hf872914334…

Vue双向绑定的思维的设计模式,Vue玩家必须深入一下。

7.装饰器模式(React必懂)

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。

有点类似我们的相框与相片的关系。

优点:装饰类和被装饰类可以独立发展,不会相互耦合。

缺点: 多层装饰比较会显得复杂。

React高阶组件的思维,React玩家必须深入一下。

2)网络协议篇

本人列举几个重点的点。建议直接tiantianUp的文章,写得比较适合观众(不像写得比较适合自己,自己看的都是写个要点去联想)。

本节内容参考:

1.巩固你的HTTP知识体系:juejin.im/post/685728…

2.前端必备的HTTP基础知识:www.jianshu.com/p/20bd68e95…

3.12期前端冲刺必备指南: juejin.im/post/684490…

1.http特点

优点

1.简单快速

每个资源得到URI是固定的,想访问某个资源,只需要输入这个资源对应的URI就可以了。

(URL(Uniform Resource Location)统一资源定位符,URI(Uniform Resource Identifier)统一资源标识符。URL是URI的子集,URL就是用定位的方式实现的URI。)

2.灵活

每个HTTP头部有个Content-Type,一个HTTP协议通过设置不同的Content-Type值,可以完成不同类型的资源的传输。

3.无连接

限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。

4.无状态

HTTP协议对于事务处理没有记忆能力。知乎一句简单回单很好:就是第二次来你无法识别它曾经来过。(人生若只如初见)

但是,在通过增加cookie和session机制的前提下,现在的网络请求其实是有状态的。

缺点

1.无状态,有时候,需要保存信息,比如像购物系统,需要保留下顾客信息等等,另外一方面,有时候,无状态也会减少网络开销,比如类似直播行业这样子等,这个还是分场景来说。

2.明文传输,即协议里的报文(主要指的是头部)不使用二进制数据,而是文本形式。这让HTTP的报文信息暴露给了外界,给攻击者带来了便利。

3.队头阻塞,当http开启长连接时,共用一个TCP连接,当某个请求时间过长时,其他的请求只能处于阻塞状态,这就是队头阻塞问题。

2.https

HTTPS协议需要到CA申请证书,一般免费证书很少,需要交费。

HTTP协议运行在TCP之上,所有传输的内容都是明文,HTTPS运行在SSL/TLS之上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的。

HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

HTTPS可以有效的防止运营商劫持,解决了防劫持的一个大问题。

3.http1.1

缓存处理

带宽优化

异常码的完善,新增了24个错误状态响应码,

Host头处理

长连接

4.http2.0

header压缩

新的二进制格式

多路复用

服务端推送

5.http缓存

参考上篇,浏览器缓存部分。

6.常见状态码

「1xx」: 代表请求已被接受,需要继续处理。

「2xx」: 表示成功状态。

「3xx」: 重定向状态。

「4xx」: 客户端错误。

「5xx」: 服务器端错误。

7.DNS解析

浏览器缓存 —>> 本地hosts文件 —>> 本地DNS解析器 —>>本地DNS服务器 —>> 其他域名服务器请求。

8.三次握手

第一次握手:建立连接时,客户端发送syn包(seq=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(seq=k),即SYN+ACK包,此时服务器进入SYN_RECV状态。

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

9.四次挥手

1、客户端发送断开TCP连接请求的报文,其中报文中包含seq序列号,是由发送端随机生成的,并且还将报文中的FIN字段置为1,表示需要断开TCP连接。(FIN=1,seq=x,x由客户端随机生成)

2、服务端会回复客户端发送的TCP断开请求报文,其包含seq序列号,是由回复端随机生成的,而且会产生ACK字段,ACK字段数值是在客户端发过来的seq序列号基础上加1进行回复,以便客户端收到信息时,知晓自己的TCP断开请求已经得到验证。(FIN=1,ACK=x+1,seq=y,y由服务端随机生成)

3、服务端在回复完客户端的TCP断开请求后,不会马上进行TCP连接的断开,服务端会先确保断开前,所有传输到A的数据是否已经传输完毕,一旦确认传输数据完毕,就会将回复报文的FIN字段置1,并且产生随机seq序列号。(FIN=1,ACK=x+1,seq=z,z由服务端随机生成)

4、客户端收到服务端的TCP断开请求后,会回复服务端的断开请求,包含随机生成的seq字段和ACK字段,ACK字段会在服务端的TCP断开请求的seq基础上加1,从而完成服务端请求的验证回复。(FIN=1,ACK=z+1,seq=h,h为客户端随机生成)

五.前端框架(复习指引)

该章节,本计划列出所有知识点。后续发现有很多好文,再加上笔者时间不足,

避免本文没了下文,笔者做一个简单的指引。(该章节后续有时间,会单独出文章,时间暂不确定,有兴趣就期待吧)

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
负载均衡
负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档