如何用原生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
相关产品推荐
相关产品推荐

