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

jQuery函数定义与事件绑定方法,嵌套函数绑定$(this)失效问题求助

Hey there! Let's break down your questions step by step, starting with how to define functions and bind them to events in jQuery, then tackling that tricky $(this) issue you're facing.


1. Defining Functions & Binding to Events in jQuery

There are a few common, flexible ways to do this depending on your use case:

Anonymous Functions (for one-off logic)

You can pass an anonymous function directly to the .on() method—this is perfect for simple, non-reusable logic like your button click handler:

$('.click_btn').on('click', function(e) {
  e.preventDefault();
  style = $(this).data().style;
  console.log(style);
});

Named Functions (for reusable logic)

If you need to reuse the same event handler across multiple elements or events, define a named function and pass its reference to .on()—just like your hover function:

function hover() {
  $(this).addClass('style3');
}

// Bind it to the mouseover event alongside other handlers
$("#calendar .day").on({
  mouseover: hover,
  click: outpatient
});

Event Delegation (for dynamic elements)

If your target elements are added to the DOM after page load (e.g., via AJAX), use event delegation to bind events to a parent element that exists on page load:

// This works even if .day elements are added later to the #calendar container
$("#calendar").on('click', '.day', outpatient);

2. Why $(this) Isn't Working in Your Nested Functions

The core issue here is how JavaScript handles this context:

  • When you bind outpatient as the click handler, inside outpatient, this correctly refers to the clicked <td> element.
  • But when you call outpatient1() or outpatient2() directly like regular functions, their this defaults to the global window object (in browsers)—not the <td> that triggered the event. That's why $(this) fails to target the clicked cell.

3. Fixing the $(this) Issue

Here are three solid, practical fixes:

Method 1: Use call() to Explicitly Set this Context

The simplest fix is to pass the this context from outpatient to outpatient1/outpatient2 using call(), which lets you manually set the this value for the function you're calling:

function outpatient() {
  if (style == "style1") {
    outpatient1.call(this); // Pass the clicked element's context
  } else {
    outpatient2.call(this);
  }
}

Now outpatient1 and outpatient2 will have this pointing to the clicked <td>, just like outpatient does.

Method 2: Save this to a Variable in outpatient

If you prefer to avoid modifying function calls, store the clicked element in a variable inside outpatient and use that variable in your logic (great if you don't need to reuse outpatient1/outpatient2 elsewhere):

function outpatient() {
  const $clickedCell = $(this); // Save the clicked element
  if (style == "style1") {
    console.log("#1");
    let clickedID = $clickedCell.attr('id');
    console.log("clickedID", clickedID);
    $clickedCell.removeClass().addClass(style);
  } else {
    console.log("#2");
    $clickedCell.nextAll(':lt(3)').addClass(style);
  }
}

Method 3: Use Arrow Functions (ES6+)

Arrow functions inherit their this context from the surrounding scope, so you can define outpatient1 and outpatient2 as arrow functions inside outpatient:

function outpatient() {
  const outpatient1 = () => {
    console.log("#1");
    let clickedID = $(this).attr('id');
    console.log("clickedID", clickedID);
    $(this).removeClass().addClass(style);
  };

  const outpatient2 = () => {
    console.log("#2");
    $(this).nextAll(':lt(3)').addClass(style);
  };

  if (style == "style1") {
    outpatient1();
  } else {
    outpatient2();
  }
}

Note: Arrow functions can't be used as standalone event handlers if you need this to refer to the element, since their this is fixed at definition time.


Full Working Code

Here's your code with Method 1 applied (using call()), which keeps your functions separate and reusable:

<!DOCTYPE html>
<html>
<head>
  <style>
    td {
      padding: 10px;
      border: solid black 1px;
    }
    table {
      border-collapse: collapse;
    }
    .is-clicked {
      background-color: aqua;
    }
    .style1 {
      background-color: red;
    }
    .style2 {
      background-color: aqua;
    }
    .style3 {
      background-color: yellow;
    }
  </style>
</head>
<body>
  <div id="calendar">
    <table>
      <tr>
        <td id="1" class="day">1</td>
        <td id="2" class="day">2</td>
        <td id="3" class="day">3</td>
        <td id="4" class="day">4</td>
        <td id="5" class="day">5</td>
        <td id="6" class="day">6</td>
        <td id="7" class="day">7</td>
      </tr>
    </table>
  </div>
  <button class="click_btn" data-style="style1">style1</button>
  <button class="click_btn" data-style="style2">style2</button>

  <script src="https://code.jquery.com/jquery-3.3.1.js"></script>
  <script>
    let style = "style1";

    $('.click_btn').on('click', function(e) {
      e.preventDefault();
      style = $(this).data().style;
      console.log(style);
    });

    function outpatient1() {
      console.log("#1");
      let clickedID = $(this).attr('id');
      console.log("clickedID", clickedID);
      $(this).removeClass().addClass(style);
    }

    function outpatient2() {
      console.log("#2");
      $(this).nextAll(':lt(3)').addClass(style);
    }

    function outpatient() {
      if (style == "style1") {
        outpatient1.call(this);
      } else {
        outpatient2.call(this);
      }
    }

    function hover() {
      $(this).addClass('style3');
    }

    $("#calendar .day").on({
      mouseover: hover,
      click: outpatient
    });
  </script>
</body>
</html>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 07:34:09