如何模拟JQuery的$(),无需手动forEach即可批量操作匹配的DOM元素
实现思路
要实现你想要的效果,核心是不要让函数返回不同类型的值,统一返回一个包装后的元素集合,通过Proxy拦截属性的读取和赋值操作,自动将操作同步到所有匹配的DOM元素上,同时兼容原生数组的遍历方法。
完整实现代码
function getEle(selector) { // 统一获取所有匹配元素,转换为数组存储 const elements = Array.from(document.querySelectorAll(selector)); // 返回Proxy代理对象,拦截所有属性操作 return new Proxy(elements, { get(target, prop) { // 优先返回数组原生方法/属性(如forEach、length) if (prop in target) { const value = target[prop]; return typeof value === 'function' ? value.bind(target) : value; } // 拦截DOM元素属性访问(如style、innerText) return new Proxy({}, { // 拦截属性赋值,批量应用到所有匹配元素 set(_, subProp, value) { target.forEach(el => { el[prop][subProp] = value; }); return true; }, // 拦截属性读取,默认返回第一个匹配元素的对应值(和jQuery行为一致) get(_, subProp) { return target.length ? target[0][prop][subProp] : undefined; } }); }, // 拦截直接赋值操作(如getEle('p').innerText = 'xxx') set(target, prop, value) { // 非数字索引的属性赋值,批量同步到所有元素 if (typeof prop !== 'symbol' && isNaN(Number(prop))) { target.forEach(el => { el[prop] = value; }); return true; } // 数组索引赋值走原生逻辑 target[prop] = value; return true; } }); }
使用示例
完全支持你想要的写法,不需要手动加forEach:
// 匹配到1个/多个p标签都会自动批量设置颜色 getEle('p').style.color = 'red'; // 批量设置所有h1的文本 getEle('h1').innerText = '统一标题'; // 批量给所有类名为item的元素添加类 getEle('.item').classList.add('active'); // 原生数组方法仍然可以正常使用,兼容旧写法 getEle('p').forEach(el => { console.log(el.textContent); }); // 读取属性默认返回第一个匹配元素的属性值 console.log(getEle('p').style.color);
可选扩展:链式API支持
如果你想要更接近jQuery的链式调用体验,可以不修改原生数组原型,直接在代理层扩展方法,比如实现css方法:
function getEle(selector) { const elements = Array.from(document.querySelectorAll(selector)); // 自定义扩展方法 const customMethods = { css(prop, value) { elements.forEach(el => el.style[prop] = value); return this; }, addClass(className) { elements.forEach(el => el.classList.add(className)); return this; } }; return new Proxy(elements, { get(target, prop) { // 优先返回自定义方法 if (prop in customMethods) { return customMethods[prop].bind(customMethods); } // 原有逻辑不变 if (prop in target) { const value = target[prop]; return typeof value === 'function' ? value.bind(target) : value; } return new Proxy({}, { set(_, subProp, value) { target.forEach(el => el[prop][subProp] = value); return true; }, get(_, subProp) { return target.length ? target[0][prop][subProp] : undefined; } }); }, set(target, prop, value) { if (typeof prop !== 'symbol' && isNaN(Number(prop))) { target.forEach(el => el[prop] = value); return true; } target[prop] = value; return true; } }); } // 链式调用示例 getEle('p').css('color', 'red').css('fontSize', '16px').addClass('text-bold');
内容的提问来源于stack exchange,提问作者LuBre
相关产品推荐
相关产品推荐

