JS中如何在不覆盖原有上下文的情况下为函数上下文绑定ID属性
如何在不覆盖现有上下文的情况下为函数绑定额外属性?
问题描述
我需要把一个id绑定到已有上下文的函数上,而且不能覆盖原有的上下文。具体来说:
setItemClickHandler是一个回调方法,已经有了自己的上下文对象,并且这个上下文带有this.index属性- 我希望在
itemClickHandler里把传入的id绑定到setItemClickHandler的上下文,让setItemClickHandler执行时的this同时拥有this.index和this.id - 注意:
bind()方法会覆盖现有上下文,所以不能用它
原代码如下:
itemClickHandler = function (id) { events = { itemClick: setItemClickHandler }; } setItemClickHandler = function () { // 这里需要同时访问this.index和this.id }
解决方案
你说得对,bind()确实会直接替换函数的上下文,所以我们得换个思路——要么给现有上下文追加属性,要么用闭包传递id同时保留原上下文。下面给你两个实用的方案:
方案1:直接给原上下文追加id属性(最简单)
如果setItemClickHandler的上下文对象是可修改的(比如是你自己创建的普通对象,不是原生对象或null),那直接在itemClickHandler里给这个上下文添加id属性就行:
// 假设之前你是这样给setItemClickHandler绑定上下文的(带index属性) const handlerContext = { index: 456 }; setItemClickHandler = setItemClickHandler.bind(handlerContext); // 修改你的itemClickHandler itemClickHandler = function (id) { // 给原上下文追加id属性 handlerContext.id = id; // 直接使用原handler,它的上下文已经包含index和id了 events = { itemClick: setItemClickHandler }; } // 现在setItemClickHandler里就能访问到两个属性了 setItemClickHandler = function () { console.log(this.index); // 输出456 console.log(this.id); // 输出传入的id }
这个方案的优点是简单直接,完全不会影响原上下文的其他属性。
方案2:用闭包包装函数(不修改原上下文)
如果你不想修改原上下文对象(比如原上下文是不可变的),可以创建一个包装函数,通过闭包捕获id,然后调用原setItemClickHandler时保留它的上下文,同时把id作为参数传递进去:
itemClickHandler = function (id) { events = { itemClick: function() { // 用call调用原handler,保留它的原有上下文,同时把id作为参数传入 return setItemClickHandler.call(this, id); } }; } // 修改setItemClickHandler接收id参数 setItemClickHandler = function (id) { console.log(this.index); // 原上下文的index属性 console.log(id); // 传入的id // 如果一定要把id放到this上,可以临时添加(不会修改原上下文) const tempThis = Object.assign({}, this, { id: id }); console.log(tempThis.id); // 同样能访问到id }
这个方案的好处是不会修改原上下文对象,适合上下文不可变的场景。
内容的提问来源于stack exchange,提问作者Ghanem
相关产品推荐
相关产品推荐

