JS
的数据类型分为基本数据类型(也称为原始数据类型)和复杂数据类型(引用数据类型)
原始数据类型又分为string
、number
、boolean
、undefined
和null
(ES6中新增Symbol
),这些都是直接按值存储在栈中的,每种类型数据占用的内存空间大小是确定的,并有系统自动分配和释放,这样带来的好处是内存可以及时得到回收,相对于堆来说,更加容易管理内存空间
引用数据类型又分为对象、数组和函数等,这些是通过拷贝和new
出来的,这样的数据存储于堆中,其实是引用类型的数据的地址指针是存储在栈中的,当我们想要访问值时,需要先从栈中获取对象的地址指针,然后通过地址指针找到堆中的所需要的数据
栈,线性结构,后进先出,便于管理;堆,一个混乱、杂乱五章,方面存储和开辟空间
内存空间管理:
JavaScript
的内存生命周期是:
1、分配你所需要的内存
2、使用分配到的内存(读、写)
3、不需要时将其释放、归还
JavaScript
有自动垃圾收集机制,最常用的就是用过标记清除算法来找到哪些对象是不再继续使用的(如a = null
),会在下次垃圾回收中找到并释放,在局部作用域中,当函数执行完毕后,局部变量也就没有存在的必要了,因此垃圾收集器很容易做出判断并且回收,但是全局变量很难判断什么时候需要自动释放内存空间,因此开发中,尽量避免使用全局变量
定义:将某一数值或对象赋给某个变量的过程,分为下面两个部分:
定义:创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的是就是基本类型的值;如果属性是引用类型,拷贝的就是内存地址,所有如果其中一个对象改变了这个地址,就会影响到另外一个对象
使用场景:
- `Object.assign()`:该方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,返回目标对象
- 展开语法`Spread`:扩展运算符...和`Object.assign()`效果是一样的
- `Array.prototype.slice()`:返回一个新的数组对象,由一个`begin`和`end`(不包括`end`)决定的原数组的浅拷贝,原始数组不会改变
定义:会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝,深拷贝相比于浅拷贝速度较慢并且花销较大,拷贝前后两个对象互不影响
使用场景:
`JSON.parse(JSON.stringify(object))`:完全改变变量1对变量2的影响,但是该方法会有一下几个问题。
- 会忽略`undefined`
- 会忽略`symbol`
- 不能序列化函数
- 不能解决循环引用的对象
- 不能正确处理`new Date()`
- 不能处理正则
- - | 和原数据是否指向同一对象 | 第一层数据为基本数据类型 | 原数据中包含子对象 |
---|---|---|---|
赋值 | 是 | 改变会使原数据一同改变 | 改变会使原数据一同改变 |
浅拷贝 | 否 | 改变不会使原数据一同改变 | 改变会使原数据一同改变 |
深拷贝 | 否 | 改变不会使原数据一同改变 | 改变不会使原数据一同改变 |
数据结构即数据元素相互之间存在的一种和多种特定的关系集合
简单来说逻辑结构就是数据之间的关系,分为两种:线性结构和非线性结构
线性结构:是一个有序数据元素的集合。 其中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的,如栈、队列、链表、线性表
非线性结构:各个数据元素不再保持在一个线性序列中,每个数据元素可能与零个或者多个其他数据元素发生联系,如二维数组、树
存储结构:逻辑结构指的是数据间关系,而存储结构是逻辑结构用计算机语言的实现。常见的存储结构有顺序存储、链式存储、索引存储以及散列存储
经典的数据结构就那么几种,list
、stack
、queue
、linkedList
、dictionary
、hash
、set
、tree
、graph
等等
数组是基础,然后为数组封装好一个List构造函数,增加长度、插入、删除、索引、遍历等工具接口,这样就构造了一个列表
列表(List),是计算机中一种常见的数据结构,是一组有序的数据,每个列表中的数据项称为元素,其中元素可以是任意数据类型
栈(Stack),又叫堆栈,是和列表类似的一种数据结构,但是更高效,因为栈内的元素只能通过列表的一端访问,称为栈顶,数据只能在栈顶添加和删除,具有后进先出的特点(LIFO,last in first out)
队列(Queue),与栈不同,它也是一种特殊的列表,队列只能在队尾插入元素,在队首删除元素,具有先进先出(FIFO,first in first out)的特点
链表(Linked-list),前面说到的栈和队列其实都是列表的一种,底层存储的数据结构都是数组,除了其外,还有链表这种数据结构,链表是一组节点组成的集合,每个节点都使用一个对象的引用来指向它的后一个节点。指向另一节点的引用讲做链如下图,链表又分为单向链表、双向链表和循环链表(单双向)
字典(Dictionary),是一种以键-值对形式存储数据的数据结构,其实,JavaScript 中的 Object 类就是以字典的形式设计的
集合(set),是由一组无序但彼此之间又有一定关系性的成员构成,每个成员在集合中只能出现一次,不同于我们之前说的字典,链表之类的,它是一种包含了不同元素的数据结构(集合中的元素称为成员),从其定义中我们可以看出它具有两个很重要的特征:首先,集合中的成员是无序的;其次,集合中的成员是不相同的,即集合中不存在相同的成员
时间复杂度和空间复杂度的高低决定着一段代码质量的好坏
时间复杂度:一个算法的时间复杂度反映了程序运行从开始到结束所需要的时间,把算法中的基本操作重复执行的次数(频度)作为算法的时间复杂度
没有循环语句,记作O(1)
,也称为常数阶。只有一重循环,则算法的基本操作的执行频度与问题规模n
呈线性增大关系,记作O(n)
,也叫线性阶
常见的时间复杂度有:
O(1)
: Constant Complexity: Constant 常数复杂度O(log n)
: Logarithmic Complexity: 对数复杂度O(n)
: Linear Complexity: 线性时间复杂度O(n^2)
: N square Complexity 平⽅方O(n^3)
: N square Complexity ⽴立⽅方O(2^n)
: Exponential Growth 指数O(n!)
: Factorial 阶乘空间复杂度:一个程序的空间复杂度是指运行完一个程序所需内存的大小。利用程序的空间复杂度,可以对程序的运行所需要的内存多少有个预先估计
一个程序执行时除了需要存储空间和存储本身所使用的指令、常数、变量和输入数据外,还需要一些对数据进行操作的工作单元和存储一些为现实计算所需信息的辅助空间
设计模式的定义:在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案
设计模式分三大类:
创建型设计模式:
创建型设计模式关注于对象创建的机制方法,通过该方法,对象以适应工作环境的方式被创建。基本的对象创建方法可能会给项目增加额外的复杂性,而这些模式的目的就是为了通过控制创建过程解决这个问题。
属于这一类的一些模式是:构造器模式(Constructor),工厂模式(Factory),抽象工厂模式 (Abstract),原型模式 (Prototype),单例模式 (Singleton)以及 建造者模式(Builder)
结构设计模式:
结构模式关注于对象组成和通常识别的方式实现不同对象之间的关系。该模式有助于在系统的某一部分发生改变的时候,整个系统结构不需要改变。该模式同样有助于对系统中某部分没有达到某一目的的部分进行重组。
在该分类下的模式有:装饰模式,外观模式,享元模式,适配器模式和代理模式
行为设计模式:
行为模式关注改善或精简在系统中不同对象间通信。
行为模式包括:迭代模式,中介者模式,观察者模式和访问者模式