You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用原生JavaScript实现jQuery data()存储对象的功能?

原生JS实现jQuery.data()的等价功能

jQuery的$(elem).data('key', value)核心是在元素对象上附加独立的存储容器,和DOM的data-*属性无关,能存任意类型数据(包括完整对象实例)。原生JS可以通过以下几种方案实现等价功能:

1. 使用Element.dataset(仅适合简单场景)

element.dataset是操作DOM的data-*属性的API,和jQuery.data()逻辑不同——它仅支持字符串类型存储,若要存对象需手动序列化:

// 存储简单字符串
elem.dataset.somekey = 'somevalue';
// 读取简单字符串
const value = elem.dataset.somekey;

// 存储对象(需序列化)
elem.dataset.user = JSON.stringify({name: 'John', age: 30});
// 读取对象(需反序列化)
const user = JSON.parse(elem.dataset.user);

缺点:数据会同步到DOM属性中,性能和隐私性不如jQuery的独立存储方案,且无法直接存函数、复杂对象。

2. 使用WeakMap(推荐方案)

WeakMap是最贴合jQuery.data()逻辑的原生实现:它以DOM元素为键,存储任意类型数据,且当元素被销毁时,对应存储条目会自动回收,不会造成内存泄漏:

// 创建全局WeakMap作为存储容器
const elementData = new WeakMap();

// 存储数据
function setData(elem, key, value) {
  if (!elementData.has(elem)) {
    elementData.set(elem, {});
  }
  const dataStore = elementData.get(elem);
  dataStore[key] = value;
}

// 读取数据
function getData(elem, key) {
  const dataStore = elementData.get(elem);
  return dataStore ? dataStore[key] : undefined;
}

// 删除指定键的数据
function removeData(elem, key) {
  const dataStore = elementData.get(elem);
  if (dataStore) {
    delete dataStore[key];
    // 若存储对象为空,清理WeakMap条目
    if (Object.keys(dataStore).length === 0) {
      elementData.delete(elem);
    }
  }
}

// 使用示例
const myElem = document.getElementById('my-elem');
setData(myElem, 'user', {name: 'Alice', role: 'admin'});
console.log(getData(myElem, 'user')); // 输出 {name: 'Alice', role: 'admin'}

该方案完全脱离DOM属性,支持任意类型存储,且自动处理内存回收,完美复刻jQuery.data()的核心能力。

3. 使用Symbol作为元素私有属性

利用Symbol的唯一性,给DOM元素添加不会冲突的私有属性存储数据:

// 创建唯一Symbol作为存储键
const DATA_STORE = Symbol('data-store');

// 存储数据
function setData(elem, key, value) {
  if (!elem[DATA_STORE]) {
    elem[DATA_STORE] = {};
  }
  elem[DATA_STORE][key] = value;
}

// 读取数据
function getData(elem, key) {
  return elem[DATA_STORE] ? elem[DATA_STORE][key] : undefined;
}

// 使用示例
const btn = document.querySelector('button');
setData(btn, 'clickHandler', () => alert('Clicked!'));
btn.addEventListener('click', getData(btn, 'clickHandler'));

缺点:若元素被长期引用,存储的数据不会自动回收,存在内存泄漏风险,安全性弱于WeakMap方案。


内容的提问来源于stack exchange,提问作者Luca Reghellin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 22:42:16