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

如何在JavaScript/jQuery的onclick中传递动态对象?

解决JavaScript/jQuery onclick事件传递动态对象的问题

我来帮你梳理下代码里的问题,然后给出几个靠谱的解决方案:

问题分析

你的代码里product变成undefined主要有这几个原因:

  • 变量提升与作用域问题:用var声明的i是函数级作用域,你在循环外就执行了hpc = handleProductsClick.bind(products[i]);,此时i还没初始化,值是undefined,所以products[i]自然也是undefined。
  • 全局变量覆盖:你把hpc设为全局变量,循环里每次赋值都会覆盖之前的,最后所有<li>的onclick都指向最后一次绑定的函数。
  • 循环闭包陷阱:就算把bind放到循环里,var声明的i会在循环结束后变成products.length,导致所有绑定的上下文都是products[products.length](也就是undefined)。

解决方案

方案1:用事件委托(推荐,优雅且无全局污染)

事件委托是最推荐的方式,不用写内联onclick,通过父元素监听子元素的点击事件,还能避免动态生成元素的事件绑定问题:

// 点击事件处理函数
function handleProductsClick(e) {
  // 从元素的data属性里取出序列化后的product
  const product = JSON.parse(decodeURIComponent($(e.target).data('product')));
  alert(JSON.stringify(product));
}

function buildProducts(products) {
  let bp = '';
  for (let i = 0; i < products.length; i++) {
    // 将product序列化为字符串并存入data属性
    const productStr = encodeURIComponent(JSON.stringify(products[i]));
    bp += `<li data-product="${productStr}">${products[i].value}</li>`;
  }
  $("#products").html(bp);
  // 给父元素ul绑定事件委托
  $("#products").on('click', 'li', handleProductsClick);
}

function getProductsFromApi() {
  const products = [{ key: 1, value: "Apple" }, { key: 2, value: "Android" } ];
  buildProducts(products);
}

getProductsFromApi();

方案2:动态创建元素并绑定闭包事件

这种方式直接用jQuery创建DOM元素,通过闭包捕获当前循环的product,避免字符串拼接的问题:

// 返回一个绑定了当前product的点击处理函数
function createProductClickHandler(product) {
  return function(e) {
    alert(JSON.stringify(product));
  }
}

function buildProducts(products) {
  const $productList = $("#products").empty();
  for (let i = 0; i < products.length; i++) {
    // 创建li元素并设置文本
    const $li = $('<li>').text(products[i].value);
    // 绑定点击事件,通过闭包传入当前product
    $li.click(createProductClickHandler(products[i]));
    // 添加到列表中
    $productList.append($li);
  }
}

function getProductsFromApi() {
  const products = [{ key: 1, value: "Apple" }, { key: 2, value: "Android" } ];
  buildProducts(products);
}

getProductsFromApi();

方案3:修复原代码的作用域问题(不推荐,仅作参考)

如果你坚持要用内联onclick,可以用let解决作用域问题,同时避免全局变量覆盖:

function handleProductsClick(product, e) {
  alert(JSON.stringify(product));
}

function buildProducts(products) {
  let bp = '';
  for (let i = 0; i < products.length; i++) {
    // 用let创建块级作用域,每次循环的i都是独立的
    const handler = handleProductsClick.bind(null, products[i]);
    // 给每个handler分配唯一的全局名称(不推荐,会污染全局)
    window[`productHandler_${i}`] = handler;
    bp += `<li onclick="productHandler_${i}(event)">${products[i].value}</li>`;
  }
  $("#products").html(bp);
}

function getProductsFromApi() {
  const products = [{ key: 1, value: "Apple" }, { key: 2, value: "Android" } ];
  buildProducts(products);
}

getProductsFromApi();

内容的提问来源于stack exchange,提问作者Abraham Gnanasingh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:39:47