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.
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);
$(this) Isn't Working in Your Nested Functions The core issue here is how JavaScript handles this context:
- When you bind
outpatientas the click handler, insideoutpatient,thiscorrectly refers to the clicked<td>element. - But when you call
outpatient1()oroutpatient2()directly like regular functions, theirthisdefaults to the globalwindowobject (in browsers)—not the<td>that triggered the event. That's why$(this)fails to target the clicked cell.
$(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.
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

