前端也要会的数据结构 (不定期更新篇)

前端的软肋

一说到前端大家脑子里只有,布局、展示数据、修改样式等等。可是数据是哪里来的呢?后端给的后端给的。数据的结构呢?后端给啥用啥。

这就是前端的一个软肋。我们的业务让我们并不需要过深入的了解数据结构,数据结构和算法是一个程序员的基础。无论是前端开发还是后端开发、还是AI机器学习大数据,我认为都需要一定的数据结构和算法知识(除了前端,其余的都是强烈的刚需。。。),前端的伙伴们学会数据结构有什么好处呢?改变思考方式,深入了解js执行的一些过程,在代码中不知不觉考虑代码层面的性能优化。用处很多,接下来开始吧。

什么是数据结构?

数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。(来自百度百科)

计算机存储是什么意思呢?就是我们常说的存储结构。

组织数据的方式与特定关系呢?就是我们的逻辑结构。

一堆按一定的存储结构和逻辑结构组合起来的数据集合就是数据结构。

这是我的一些理解。所以当一种数据结构摆在我的面前我就会考虑,它是以哪种形式存储起来,它有什么特殊的逻辑组合起来。这种方式有哪些好处呢?当我明白这些的时候,这种数据结构我就算基本了解了。

首先我们先说一下线性表,线性表是数据的逻辑结构,元素之间是一对一的关系,你个线性表中,任何一个元素的前一个或者后一个都只有一个元素,而不会出现任何一个元素的前一个或者后一个元素对应多个元素的情况。

线性表分为一般性的线性表、与受限的线性表。一般性的线性表就好比数组。就是最常见的一般性线性表,而受限的线性表就是栈与队列。

好了好了 我们开始正题了

你好 神奇的栈结构

栈型结构,最大的特点是什么?先进后出,先进入的元素要比后进入的元素更晚的离开这个容器,这像什么一堆摞起来的书籍。你这能拿走书的最上面的。(你要是给书推倒了,那就只能说明你比较睿智)

所以我们要实现一个栈型结构很自然的想到了

容器:数组

方法:数组的push与pop方法 下面开始实现一个栈的构造函数

function Stack(){// 用let创建一个私有容器,无法用this选择到dataStore;let dataStore = [];// 模拟进栈的方法 this.push = function(element){dataStore.push(element);};// 模拟出栈的方法,返回值是出栈的元素。this.pop = function(){return dataStore.pop();};// 返回栈顶元素this.peek = function(){return dataStore[dataStore.length-1];  };// 是否为空栈this.isEmpty = function(){return dataStore.length === 0 };// 获取栈结构的长度。this.size = function(){return dataStore.length;};//  清除栈结构内的所有元素。this.clear = function(){dataStore = [];}
}

好了伙伴们 栈的构造函数我们已经写好了。

// 一个单独的栈生成了。
let stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(5);
stack.peek(); // return 5
stack.size(); // return 3
stack.clear();
stack.peek(); // undefined

一个基本的栈型结构就实现了。 真的很是简单。但是这个东西在js中有什么用处呢?

在js中的用处

用处很大,首先我们都知道递归如果没有设置好边界值,就会报堆栈溢出。 什么意思??? 我们的js代码在执行的时候,会生成一个调用栈(里面装满了所有执行中的函数)

在这个调用栈第一个进栈的也就是压在最下面的就是全局函数,这个全局函数只会在浏览器关闭后才会出栈,浏览器关闭了这个堆栈也就随之消失了。 当浏览器执行下去的时候执行一个函数的时候,就会把这个执行中的函数加入到调用栈中,被调用了就要进调用栈(比较好理解吧),同时控制权也会转交给这个函数,这个函数中如果有别的函数,执行到别的函数时,做着一样的事情,进栈。当任何一个函数执行结束之后,那么不好意思,他就要退栈了。离开这个调用栈了。因为调用栈中内容过多,代表着垃圾资源没有回收,从而导致浏览器卡顿,这是不合理的,执行完毕就会退栈。

退栈之后,那么执行权就要交回到包含着它的函数了。

堆栈的三种场景

1:递归是一种怎样的情况呢?

当我们没有考虑递归的出口的时候,
简化函数
function fn(){let a = 1; fn()
}
fn()  // 报错!!!! Maximum call stack size exceeded// 最大调用堆栈大小超过

当我没有设定出口时,并没有任何一个函数会出栈,在不断的循环调用后,你的堆栈肯定不会是无限的,那么就只好提醒你堆栈溢出,程序报错。

2: 你知道redux的洋葱模型图吗?

所谓redux的洋葱模型(其实redux我没用过,但是在公司分享会上听过一段对于这个洋葱模型图的分享),大家也可以理解一下express框架的写接口时的next函数。

在我们洋葱在最外层执行完毕后就会进入里面,到最内部后再循坏退出来。

function fn1(){console.log('fn1 first');fn2()console.log('fn1 last');
}
function fn2(){console.log('fn2 first');fn3()console.log('fn2 last');
}
function fn3(){console.log('fn3 first');console.log('fn3 last');
}
fn1()

打印结果中我们可以看出,fn1执行的时候在,遇到fn2执行进栈后,将控制权转交给fn2,fn2执行遇到fn3执行进栈,将控制权交给fn3,fn3执行完毕后退栈,控制权还给fn2,那么fn2后面的代码会继续执行,fn2的代码执行完毕,退栈。继续执行fn1后面的代码直到退栈。可能这种简单的模式大家看起来比较清晰,如果有比较复杂的内容,大家记得画图不要弄错了。

3: 不说你就会忘的闭包

为什么闭包使用过多会导致程序卡顿,性能不好???

这个问题很让人费解,但是扯上调用栈后,我觉得可以解释一波(代码我就不上了,大家可以去找找闭包得代码看一看) 闭包得私有变量怎么产生的? 在一个函数执行后,它执行完毕就一定会退栈。

function A(){var count = 0;function B(){count   ;console.log(count);}return B;
}
var C = A();
C();// 1
C();// 2
C();// 3

不好意思我食言了,方便大家理解还是上一波代码吧。

在A函数执行得时候,我们发现执行过程中,遇到B函数,好了它开始调用进栈执行,执行完毕后,控制权回归A函数,然后把B函数return出去了。B函数中保持对count变量的引用,你就把它return出去了????好吧你愿意你就这么干。

B函数被推出去到外面的世界(外面的函数体内);将B赋值给C,好了C需要count变量的支持,count就不能离开内存(也就是不能被垃圾回收);拿咋办? A函数执行完了我也该离开了(函数执行完毕后,函数内部的变量会被回收掉)。不好意思,外面执行着的函数还有对你的引用,那不好意思你别退栈了,并不允许离开调用栈,因为要保留count变量的环境。

好吧每一个这种情况就会有几个函数无法退栈,调用栈里面的内容越堆越多。就会越加卡顿。一辆公交车,咱们的乘客到站就下车了,但是总有几个乘客死活不下车,车上人越来越多,车也越来越沉,好吧跑起来就越来越慢了。

是时候结个尾了

在不理解栈的时候,我很难去想以上几种情况,数据结构真的在改变我的思路,一切的知识点都在这些基础中有着验证,夯实基础,我认为数据结构也不应该是前端的加分项,而是比会项。最后的最后,我用我听过的一句很经典的话来结尾好了

我们写的代码不是为了更好的和人去沟通,而是去更好的和机器沟通

最后打个广告(我们一起维护的学习公众号)

公众号主要面向的是初级/应届生。内容包含我们从应届生转换为职场开发所踩过的坑,以及我们每周的学习计划和学习总结。 内容会涉及计算机网络算法等基础;也会涉及前端,后台,Android等内容~

求关注,不迷路

我们基友团其他朋友的文章:

Android基友

Java基友

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367314.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙系统8月9日发布,8月9日,华为发布EMUI10.0系统+展示鸿蒙系统

8月9日,华为将召开华为全球开发者大会,本次大会邀请了5000名全球开发者、1500位合作伙伴,是华为历来规模最大的一次会议。在华为开发者大会上,华为将推出EMUI 10.0系统,由华为消费也业务软件总裁王成录主讲。EMUI是手机…

matlab main函数_Python 和MATLAB 制作Gif 图像

主要内容概述:预备知识MATLAB 代码实现GIF使用imageio 生成GIF使用animation 交互式方式生成GIF总结0,预备知识首先了解下什么是GIF 图片,以及常用的图片格式。GIF的全称是Graphics Interchange Format,可译为图形交换格式&#x…

ORB-SLAM2的特征提取算法

ORB-SLAM2跟踪线程对相机输入的每一帧图像进行跟踪处理,如下图所示,主要包括4步,提取ORB特征、从上一帧或者重定位来估计初始位姿、局部地图跟踪和关键帧处理。 以下结合相关理论知识,阅读ORB-SLAM2源代码,从而理解ORB…

引导界面图标好大_游戏里那些图标和界面,原来是这么设计出来的?

UI设计最硬核的思维 就是功能微信现在在做一种全面连接的功能,而游戏需要实现的是人机互动的功能。实现并完善功能,是互联网、游戏、网站、渴望UI人才的根本原因。如果说有电脑的世界是一片很大的面,那么可视化的操作,都是UI设计师…

爬格子呀9.17(图论)

刘汝佳的紫书差不多就告一段落吧,我觉得可以了,怎么说呢,这书也陪着自己走了一年多了吧,也目睹了从一个啥也不会的萌新到一个稍微会一点的萌新的转变。 差不多开始下本书吧,自己也大三了,时间真的有点紧啊w…

一个vue加egg.js的博客

之前自己的博客是用hexo做的,后面想做一个有后台的博客就打算用vue加node来试试,于是就有了这个博客。 项目地址 W-Blog W-Blog是一个基于vue和node的小小小博客 前端用vue,后端用egg.js 快速入门 技术栈 前端: 用户端&#…

android音量图标不见了,电脑声音图标不见了如何解决?

最近有电脑用户反映,看视频时觉得声音太小了,要调大点声,却发现任务栏上的声音图标不见了,想调个声音都难。那么,电脑声音图标不见了如何解决呢?我们一起往下看看。方法步骤一、XP系统下找回任务栏上的声音图标1、重启…

认识iOS系统架构

关于本文: 文章主要介绍iOS系统架构中的四层结构的内容、常用的框架、大致的功能,然后对iOS开发人员的发展提出自己的一些拙见。 一、iOS系统是基于UNIX系统,所有从系统稳定性上来说的确比其他操作系统的产品要好。 iOS在系统架构上分为4层&a…

Java泛型教程–示例类,接口,方法,通配符等

泛型是Java编程的核心功能之一,它是Java 5中引入的。如果您使用的是Java Collections ,并且版本5或更高版本,则可以肯定使用了它。 在集合类中使用泛型非常容易,但是它提供了比仅创建集合类型更多的功能,我们将在本文中…

html5中音乐播放器怎么写,打造属于自己的音乐播放器 HTML5之audio标签

我的音乐播放器HTML5中增加了Audio和Video标签,这两个标签的用法非常相似。功能却是相当强大,我们先来看一下Audio标签各个浏览器的支持情况。这里用的依然是Can I Use这个在线网站,相信学习前端的同学应该都不陌生。Can I Use我们可以看到&a…

初识react(四) react中异步解决方案之 redux-saga

回顾 初识react(一) 揭开jsx语法和虚拟DOM面纱初识react(二) 实现一个简版的html redux.js的demo初识react(三)在 react中使用redux来实现简版计数器初识react(四) react中异步解决方案之 redux-saga初识react(五) 数据流终极解决方案 dva(零配置) 今天demo是实现一个异步的计…

C# WinFrom 关于MDI

dev是一个牛B 到没边的控件 我们正常用winform做个原始mdi窗体 一点都不好看 但 用的dev只需要一个控件 就可让显示舒服多了 建一个项目 上边放一个 xtraTabbedMdiManager1 一个button1 button1.click如下: Form frm new Form(); frm.MdiParent this; frm.Text &…

Jfinal 文件上传

JFinal上传文件 uploadify 可以在http://www.uploadify.com/ 下载。 在原项目的基础上。 uploadify使用&#xff1a; <input id"file_upload_1" name"file_upload" type"file" multiple"true"> /** param uploader 文件上传方法…

轻量级的开源集成:Apache Camel还是Spring集成?

首先&#xff0c;为全面披露信息&#xff0c;在过去的1.5年中&#xff0c; 我一直担任 FuseSource&#xff08;现为Red Hat&#xff09; 的顾问&#xff0c;为零售&#xff0c;运输&#xff0c;银行/金融等不同行业的大型和小型公司提供SOA和集成项目支持。我的专长是使用该领域…

WePY:在质疑中前进 | 文末福利

WePY 作者介绍 Q: 先介绍一下自己吧~ Gcaufy: 我 2011 年大学毕业之后&#xff0c;阴错阳差的走上了 Web 开发的道路。15 年之前算是自由职业 SOHO 工作&#xff0c;主要给一些国外的大公司做外包系统&#xff0c;更多的是做后端开发。15 年之后以前端工程师的身份加入腾讯&a…

MySQL/MariaDB表表达式(3):视图

视图是表表达式的一种&#xff0c;所以它也是虚拟表。对视图操作的时候会通过语句动态的从表中临时获取数据。 1.创建、修改视图 CREATE [OR REPLACE][ALGORITHM {UNDEFINED | MERGE | TEMPTABLE}]VIEW [IF NOT EXISTS] view_name [(column_list)]AS select_statement[WITH [C…

Event Loop 其实也就这点事

前段时间在网上陆续看了很多关于 Event loop 的文章&#xff0c;看完也就混个眼熟&#xff0c;可能内心深处对这种偏原理的知识有一些抵触心情&#xff0c;看完后也都没有去深入理解。最近在看 Vue 的源码&#xff0c;在读到关于 nextTick 的实现时&#xff0c;总有一种似曾相识…

Kudu系列: Kudu主键选择策略

每个Kudu 表必须设置Pimary Key(unique), 另外Kudu表不能设置secondary index, 经过实际性能测试, 本文给出了选择Kudu主键的几个策略, 测试结果纠正了我之前的习惯认知. 简单介绍测试场景: 表中有一个unqiue字段Id, 另外还有一个日期维度字段histdate, 有三种设置kudu PK的方法…

OSS网页上传和断点续传(OSS配置篇)

OSS网页上传和断点续传主要根据BrowserJS-SDK和相关文档整理而得&#xff0c;快速构建OSS上传应用 一、Bucket设置 浏览器中直接访问OSS需要开通Bucket的CORS设置 将allowed origins设置成 *将allowed methods设置成 PUT, GET, POST, DELETE, HEAD将allowed headers设置成 *将e…

小程序各种姿势实现登录

喜闻乐见的背景时间--由于最近接触小程序比较多&#xff0c;又刚好经历过小程序的自动登录时代以及现在的点击登录时代。结合自己的实践以及观察到其他小程序的做法&#xff0c;就有了这篇小分享~ 本文可能涉及的内容-- 更新 首先感谢shaonialife同学的精彩评论~ 可能由于用词…