为啥这被绑定在这些箭头调用之一中,而不是另一个?
Posted
技术标签:
【中文标题】为啥这被绑定在这些箭头调用之一中,而不是另一个?【英文标题】:Why is this bound in one of these arrow invocations, but not the other?为什么这被绑定在这些箭头调用之一中,而不是另一个? 【发布时间】:2021-07-13 05:38:24 【问题描述】:我无法准确理解为什么 this
在某些情况下具有价值,而在其他情况下则没有。我维护了一个库,为了解释我的困惑,它被精简到最低限度,如下所示:
const arrayify = f =>
console.log('init', f.name, !!this);
return function (thingOrThings, ...args)
console.log('arrayify for ', f.name, !!this);
return [thingOrThings].map(t => f.call(this, t, ...args));
;
;
class Utils
Object.assign(Utils.prototype,
setProperty: arrayify(function setPropertyFunc(layer, prop, value)
console.log('setPropertyFunc called', !!this); // outputs true
),
hoverPopup(layers, cb, popupOptions = )
console.log('hoverPopup init', !!this);
arrayify(function hoverPopupFunc(layer, cb)
console.log('hoverPopupFunc called', !!this); // outputs false
)(layers, cb);
,
);
(它看起来过于复杂,因为我删除了所有实际有用的东西。但基本上arrayify
允许函数采用单个事物或事物数组,并隐式运行在数组中的每个项目上后一种情况。)
我这样称呼它:
const U = new Utils();
U.setProperty('mylayer', 'lineColor', 'red');
U.hoverPopup('mylayer', () => 1);
输出:
init setPropertyFunc false
arrayify for setPropertyFunc true
setPropertyFunc called true
hoverPopup init true
init hoverPopupFunc false
arrayify for hoverPopupFunc false
hoverPopupFunc called false
所以在第一种情况下,调用U.setProperty
调用arrayify
,并且this
(在arrayify
内部)有一个值。同样this
在返回给setProperty
的函数内部也有一个值。
第二个,U.hoverPopup
调用arrayify
没有this
值,返回的函数中也没有this
值。
我无法理解第二种情况的不同之处。尤其令人困惑的是,this
没有在 setPropertyFunc
的 init 中定义,但 在嵌入函数中定义,而 hoverPopupFunc
的情况正好相反
我真的很希望在这两种情况下都定义this
- 在第二种情况下我怎样才能实现呢? (在hoverPopup
的情况下,必须进行一些初始化,所以它并不像“对数组中的每个项目都执行此操作”那么简单)
【问题讨论】:
【参考方案1】:添加我自己的解释以帮助更好地理解这一点。
对象实例化后,U
基本上是这样的:
setProperty: function (thingOrThings, ...args)
console.log('arrayify for ', f.name, !!this);
return [thingOrThings].map(t => /* ... */);
,
hoverPopup: function(layers, cb, popupOptions = )
console.log('hoverPopup init', !!this);
arrayify(function hoverPopupFunc(layer, cb)
console.log('hoverPopupFunc called', !!this);
)(layers, cb);
所以,此时,setProperty
只是对象上的一个函数,所以当它被调用时,它当然具有this
的值。这个函数是由另一个函数(无论是否箭头)创建的这一事实是无关紧要的。
hoverPopup
也是对象上的一个函数,也有一个this
的值。但是当它调用arrayify
时,该调用不具有this
值,因为它不满足任何the four rules
试图将this
的值绑定到arrayify
是行不通的,因为它是一个箭头函数。但是你可以给arrayify返回的函数绑定一个值:
hoverPopup(layers, cb, popupOptions = )
console.log(`hoverPopup init $this === U`);
arrayify(function hoverPopupFunc(layer, cb)
console.log(`hoverPopupFunc called $this === U`); // outputs true
).call(this, layers, cb);
,
【讨论】:
【参考方案2】:查看调用返回函数的位置和方式以了解调用上下文 - this
。
在第一种情况下,原型上的setProperty
方法是返回的函数,它被作为实例的属性调用:
U.setProperty('mylayer', 'lineColor', 'red'); // outputs true
// ^ calling context: this
但在第二种情况下,没有调用上下文:
arrayify(function (layer, cb)
console.log('hoverpopup', !!this); // outputs false
)(layers, cb);
这只是一个可以立即调用的普通函数。简单一点:
arrayify(someFn)(layers, cb)
被调用的函数 - 整个 arrayify(someFn)
部分 - 不是对象的一部分,而是一个独立的变量,因此没有调用上下文。
我真的很想在这两种情况下都定义这个 - 在第二种情况下我怎样才能做到这一点?
使用.call
调用具有特定this
的函数。
hoverPopup(layers, cb, popupOptions = )
// do some other initialisation here
const fn = function (layer, cb)
console.log('hoverpopup', !!this); // outputs false
;
arrayify(fn).call(this, layers, cb);
,
这会起作用,因为当在 hoverPopup
的主体内时,this
是实例:
U.hoverPopup('mylayer', () => 1);
// ^ calling context: this
这样做arrayify(fn).call(this, layers, cb);
会随心所欲地传递它。
【讨论】:
啊,我明白了。这很有意义。我曾尝试使用.call()
,但放错了位置。以上是关于为啥这被绑定在这些箭头调用之一中,而不是另一个?的主要内容,如果未能解决你的问题,请参考以下文章
WPF)为啥完全相同的绑定在一个地方工作,而在另一个地方却不行?