手写Map集合【JavaScript】

Map集合的出现以及为什么使用Map?

map集合存储的是键值对,键值对数据集合的特点:键不可重复

在map出现之前,我们使用的是对象的方式来存储键值对,键是属性名,值是属性值。

使用对象存储有以下问题:

  1. 键名只能是字符串

  2. 获取数据的数量不方便

  3. 键名容易跟原型上的名称冲突


如何创建map以及map如何操作

new Map(); //创建一个空的map
new Map(iterable); /iterabal是一个长度为2的数组,数组第一项表示键,数组的第二项表示值

1.如何进行后续操作

size:只读属性,获取当前map中键的数量

set(键, 值):设置一个键值对,键和值可以是任何类型

  • 如果键不存在,则添加一项
  • 如果键已存在,覆盖原来的值

get(键): 根据一个键得到对应的值

has(键):判断某个键是否存在

delete(键):删除指定的键

clear(): 清空map

2.和数组互相转换: [...map]

3.比较键的方式和set相同(Object.is)

4.遍历

  • for-of,每次迭代得到的是一个长度为2的数组
  • forEach,通过回调函数遍历
  • 参数1:每一项的值
  • 参数2:每一项的键
  • 参数3:map本身

Map实现

构造器

    constructor(iterator = []) {
        if (typeof iterator[Symbol.iterator] !== "function") {
            throw new TypeError(`你提供的${iterator}不是一个可迭代对象`)
        }
        this._data = []
        for (const item of iterator) {
            if (typeof item[Symbol.iterator] !== "function") {
                throw new TypeError(`${item}不是一个可迭代对象`)
            }
            //得到迭代器,调用迭代器拿到每一项的key和value
            const iterator = item[Symbol.iterator]()
            const key = iterator.next().value
            const value = iterator.next().value
            this.set(key, value)
        }
    }

辅助函数

    /**
     * 根据key从内部的数组中找到对应的数据项
     * @param {*} key 
     */
    _getObj(key) {
        for (const item of this._data) {
            if (this._isEqual(item.key, key)) {
                return item
            }
        }
    }

    /**
     * 判断两个数据是否相等
     * @param {*} data1 
     * @param {*} data2 
     */
    _isEqual(data1, data2) {
        if (data1 === 0 && data2 === 0) return true
        return Object.is(data1, data2)
    }

set

    set(key, value) {
        const obj = this._getObj(key)
        if (obj) {
            //覆盖
            obj.value = value
        }
        else {
            //添加
            this._data.push({
                key,
                value
            })
        }
    }

get

    get(key) {
        const obj = this._getObj(key)
        if (obj) {
            return obj.value
        }
        return undefined
    }

has与size(只读属性)

    has(key) {
        return this._getObj(key) !== undefined
    }
    get size() {
        return this._data.length
    }

删除与清除

    delete(key) {
        for (let index = 0; index < this._data.length; index++) {
            let temp = this._data[index]
            if (this._isEqual(temp.key, key)) {
                this._data.splice(index, 1)
                return true
            }
        }
        return false
    }

    clear() {
        this._data.length = 0
    }

满足可迭代协议

    //需要满足可迭代协议
    *[Symbol.iterator]() {
        for (const obj of this._data) {
            yield [obj.key, obj.value]
        }
    }

    forEach

    forEach(callback) {

        for (const obj of this._data) {

            callback(obj.value, obj.key, this)

        }

    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值