我跟随凯尔辛普森的YDKJS系列书,有一个关于显式还是硬装订的问题。凯尔解释说,仅靠显式绑定并不一定足以保证我们传递回调的函数将保留回调的this
上下文。他列举了一些例子,在这些情况下,库/框架中的函数有时会恼怒地强制this
在回调中引用什么--传递给与显式设置它相同的东西。因此,我试着测试这看起来可能是什么样子,并假设以下代码的行为会有所不同:
function foo() {
console.log(this.a);
}
var obj = {
a: 5
}
var obj2 = {
a: 10
}
function bar(f) {
f.call(obj2); // 5 --> expected explicit binding to be overwritten here, but this doesn't happen (expected 10 and got 5)
}
bar(foo.bind(obj)); // explicit binding made here
我认为这将成功地覆盖this
所指的内容(这就是我们需要硬绑定的原因)。首先,下面是使用硬绑定的相应示例。
function foo() {
console.log(this.a);
}
var obj = {
a: 5
}
var obj2 = {
a: 10
}
// hard binding here
function baz() {
foo.call(obj);
}
function bar(f) {
f.call(obj2); // 5 --> Here, it makes sense that we would get 5
}
bar(baz);
让我解释一下我认为硬约束的目的是:
我认为bar可以覆盖回调的this
上下文。事实上,凯尔·辛普森本人认为这是可能的,也是最初难以约束的原因。硬绑定解决了这个显然存在的问题,因为即使bar强制更改回调baz的this
上下文,更改baz的this
引用实际上并不会起到任何作用,因为它不会影响this
在foo.call(obj)
中所指的内容,而且bar不能改变这一点。
但是,我正在尝试复制显式绑定失败的场景,但似乎不能这样做。我不能覆盖函数的this
上下文,即使它不是硬绑定和显式绑定。有什么想法会让我误入歧途吗?
编辑:当我不将函数作为回调传递时,在全局范围内,我可以执行foo.call(obj)
和获取5,然后执行foo.call(obj2)
和get 10,但这不是覆盖吗?这些只是具有不同绑定的foo调用的两个不同实例。
发布于 2021-06-24 09:08:22
在阅读了注释之后,我做了一些研究和测试,试图打破bind
方法,发现当使用new
运算符调用绑定函数时,将忽略预先赋值的this
值,并保留预先赋值的参数。
因此,绝对有一种方法可以更改函数的以前绑定的this
(参见下面的脚本),操作“硬绑定”示例可以避免这种情况!
我必须指出,我也尝试了其他丑陋的东西,如eval
,但没有成功。
无论如何,说到库,处理用户定义的函数(或回调)上下文对我来说似乎是一种糟糕的做法。做下面的事太疯狂了,我不认为有人会这么做。然而,为了知识而知道这一点是很好的。
const a = {value: 1};
const b = {value: 2};
const fn = function() {console.log(this.value);};
const boundA = fn.bind(a);
const hardBoundA = function() {fn.call(a);};
const reBoundB = (new boundA()).constructor.bind(b);
const hardReBoundB = (new hardBoundA()).constructor.bind(b);
boundA();
hardBoundA();
reBoundB()
hardReBoundB();
https://stackoverflow.com/questions/68111664
复制相似问题