实例化Bar函数时,如何在不传入foo元素的情况下访问该元素?
问题:如何在Bar构造函数内部访问关联的foo元素(无需将foo作为参数传入)
先看原代码:
<input type="text" name="foo" class="form-control" id="foo"> <script> function Bar(param1, param2) { this.param1 = param1; this.param2 = param2; // 怎么在这里访问foo元素? } let foo = document.getElementById('foo'); foo.bar = new Bar('something', 'something else'); </script>
核心难点:在new Bar()执行的同步阶段,这个Bar实例还没被赋值给foo.bar,所以构造函数里没法直接拿到foo元素。但可以通过以下几种技巧实现关联访问:
方案1:用属性拦截自动绑定元素
通过Object.defineProperty拦截foo的bar属性赋值操作,在赋值时给Bar实例添加指向foo的引用,甚至可以触发实例的初始化方法在绑定后访问元素:
function Bar(param1, param2) { this.param1 = param1; this.param2 = param2; // 初始化方法,绑定元素后执行 this.init = function() { console.log('访问到foo元素:', this.element.id); } } let foo = document.getElementById('foo'); // 拦截foo的bar属性 Object.defineProperty(foo, 'bar', { set(instance) { // 给Bar实例挂载元素引用 instance.element = this; // 触发初始化,此时就能访问元素了 instance.init(); // 把实例存在私有属性里用于读取 this._bar = instance; }, get() { return this._bar; } }); // 赋值时自动触发绑定 foo.bar = new Bar('something', 'something else');
方案2:用工厂函数封装实例创建
通过工厂函数负责把元素和Bar实例关联起来,构造函数本身不需要接收元素参数:
function Bar(param1, param2) { this.param1 = param1; this.param2 = param2; // 这里可以直接访问this.element console.log('访问到foo元素:', this.element.id); } // 工厂函数:创建实例并绑定元素 function createBar(element, param1, param2) { const barInstance = new Bar(param1, param2); barInstance.element = element; return barInstance; } let foo = document.getElementById('foo'); foo.bar = createBar(foo, 'something', 'something else');
方案3:用WeakMap存储实例与元素的关联(异步访问)
如果可以接受异步访问,用WeakMap存储实例和元素的映射关系,在赋值后通过微任务或宏任务获取:
const elementMap = new WeakMap(); function Bar(param1, param2) { this.param1 = param1; this.param2 = param2; // 用微任务等待赋值完成后获取元素 queueMicrotask(() => { const fooElement = elementMap.get(this); if (fooElement) { console.log('访问到foo元素:', fooElement.id); } }); } let foo = document.getElementById('foo'); // 赋值时同步存入映射关系 elementMap.set(foo.bar = new Bar('something', 'something else'), foo);
内容的提问来源于stack exchange,提问作者Duddy67
相关产品推荐
相关产品推荐

