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

如何模拟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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 01:06:06