数组
数组(Array)是一种线性表数据结构。它用一组连续的存储空间来存储一组具有相同类型的数据。
线性表
数据排成一列,每个数据最多有前后两个方向。数组、链表、队列、栈都是线性表。
连续内存空间、相同数据类型
因为连续内存空间,获得随机访问特性。但是写入速度慢。注意:随机访问的时间复杂度是O(1),查找时间复杂度是O(n)。
不过也因为连续内存空间,需要向系统申请固定长度内存空间来存储。过长或过短时可以启用扩容缩容策略。
JS代码实现
JS原本就有Array对象,但是它不是纯粹的数组结构。先来看段代码:
let arr = [100, 12.3, 'red', 'blue', {}];
arr[arr.length] = [];
arr.length // 6
arr[arr.length - 1] // []
发现有这些问题:
- 数组可以添加多种类型
- 数组没有固定长度,似乎可以自动扩容
V8引擎中的数组实现
Array的基类是Object,所以可以存储不同的类型- 数组基于两种形式存在
- 快数组,基于
数组实现 - 慢数组,基于
散列表实现
- 快数组,基于
- 快数组会自动扩缩容
- 快慢数组的区别
- 存储方式:快数组是在内存中是连续的,慢数组是零散的
- 优势:快数组遍历、查找效率略高,慢数组内存空间利用率高。
- 当满足特定条件时,数组会在
快数组和慢数组间自动切换。
代码实现
我们要实现的功能包括:
- 指定数组长度
- 统一数据类型
- 随机访问,时间复杂度O(1)
- 查询,时间复杂度O(n)
class MyArray extends Array {
constructor () {
if (!arguments.length) throw new Error('缺少必要参数:space')
if (typeof arguments[0] !== 'number') throw new Error('分配内存空间必须为数字')
const argLength = arguments.length - 1
const array = [...arguments].filter((i, k) => k !== 0)
if (array.length >= arguments[0]) throw new Error('数组长度超出分配空间')
super(...array)
this.space = arguments[0]
this.type = null
if (array.length) {
const { type, objectType } = this._getType(arguments[1])
this.type = type
this.objectType = objectType
}
if (argLength > 1) {
if (!this._isSameType(array)) {
throw new Error('数组类型必须一致')
}
}
}
// 获取对象类型
_getType (target) {
const type = typeof target
return {
type,
objectType: type === 'object'
? Object.getPrototypeOf(target).constructor
: null
}
}
// 获取数组是否同一类型
_isSameType (arr) {
for (let i = 0; i < arr.length; i++) {
if (this.objectType === null) {
if (typeof arr[i] !== this.type) return false
} else {
if (!(arr[i] instanceof this.objectType)) return false
}
}
return true
}
// 添加元素
push (...arg) {
if (this.length + arg.length > this.space) {
throw new Error('数组长度超出分配空间')
}
if (!this._isSameType(arg)) {
throw new Error('数组类型必须一致')
}
Array.prototype.push.call(this, ...arg)
}
}
function A() {}
function B() {}
var a1 = new A()
var a2 = new A()
var b1 = new B()
var arr = new MyArray(4, a1, a2)
arr.push(a1)
// arr.push(b1) // error 类型错误
// arr.push('a') // error 类型错误
// arr.push(a1, a2) // error 超出长度
console.log(arr)
当然还有很多可以完善的地方,这里就不细写了。
原创不易,欲转先告知,欢迎加我交流: