在JavaScript中如何找到HTML元素所属的对象?
问题描述
假设我有如下代码(已修正几处语法笔误):
let myList = new Map(); let something = new objectMaker(); myList.set(someIndex, new objectMaker()); // 原代码中`object`应为`myList` function objectMaker(){ this.parentThing = document.createElement("div"); // 原代码缺少`document.`前缀 this.childThing = document.createElement("div"); this.parentThing.onclick = clickyFunction(); // 以下是函数调用的细节 this.parentThing.id = someIndex + "something"; }
现在的问题是,调用clickyFunction()时如何找到该元素所属的objectMaker对象。我目前的解决方案大致如下:
this.parentThing.onclick = function(){clickElement(event,this);};
当点击childThing时,e.srcElement会指向childThing,而this参数会指向this.parentThing,因此我不得不通过循环遍历myList来匹配对应的实例:
function clickyFunction(e, callingObject) { for (let key of myList.keys()) { if (myList.get(key).parentThing.id == callingObject.id){ // 找到对应的父对象 ...
有没有办法直接将objectMaker的实例传递给clickyFunction()(无论点击哪个元素)?这似乎是更优雅的解决方案。或者我应该从整体上改变程序的组织结构?
解决方案
方法1:用箭头函数绑定实例
箭头函数会继承外层作用域的this(也就是objectMaker的当前实例),无需额外绑定就能直接在回调中访问实例:
function objectMaker(){ this.parentThing = document.createElement("div"); this.childThing = document.createElement("div"); // 箭头函数保留外层this指向,直接传递实例给clickyFunction this.parentThing.onclick = (e) => clickyFunction(e, this); this.parentThing.id = someIndex + "something"; // 记得将子元素添加到父容器中 this.parentThing.appendChild(this.childThing); } function clickyFunction(e, instance) { // instance就是当前点击元素所属的objectMaker实例 console.log("点击的元素:", e.target); console.log("对应的实例:", instance); }
方法2:用bind()绑定实例
通过bind()方法可以将objectMaker实例绑定到回调函数的this上,或者直接作为参数固定传递:
function objectMaker(){ this.parentThing = document.createElement("div"); this.childThing = document.createElement("div"); // 绑定回调的this为当前实例 this.parentThing.onclick = clickyFunction.bind(this); this.parentThing.id = someIndex + "something"; this.parentThing.appendChild(this.childThing); } function clickyFunction(e) { // 这里的this就是绑定的objectMaker实例 console.log("对应的实例:", this); }
方法3:给DOM元素挂载自定义实例属性
直接将objectMaker实例挂载到DOM元素的自定义属性上,点击时直接从元素上获取:
function objectMaker(){ this.parentThing = document.createElement("div"); this.childThing = document.createElement("div"); // 将实例挂载到父、子元素上 this.parentThing.instance = this; this.childThing.instance = this; this.parentThing.onclick = clickyFunction; this.parentThing.id = someIndex + "something"; this.parentThing.appendChild(this.childThing); } function clickyFunction(e) { // 优先用currentTarget(绑定事件的元素)获取实例,避免点击子元素时的差异 const instance = e.currentTarget.instance; console.log("对应的实例:", instance); }
优化程序结构:事件委托
如果需要管理大量objectMaker实例,推荐使用事件委托——将点击事件绑定到所有实例容器的共同父元素上,通过事件冒泡统一处理,无需给每个元素单独绑定事件:
// 假设所有objectMaker的parentThing都挂载到这个容器中 const container = document.getElementById("instance-container"); // 给父容器绑定一次事件 container.addEventListener("click", function(e) { // 找到最近的parentThing元素(根据id后缀匹配) const targetParent = e.target.closest("[id$='something']"); if (targetParent) { // 直接获取挂载的实例 const instance = targetParent.instance; clickyFunction(e, instance); } }); function objectMaker(){ this.parentThing = document.createElement("div"); this.childThing = document.createElement("div"); this.parentThing.instance = this; this.parentThing.id = someIndex + "something"; this.parentThing.appendChild(this.childThing); // 将实例容器添加到父容器中 container.appendChild(this.parentThing); }
内容的提问来源于stack exchange,提问作者user1833028
相关产品推荐
相关产品推荐

