如何覆盖';这';javascript中绑定函数的参数
我有一个已经使用function.prototype.bind方法绑定的函数。不知何故,我想重写绑定函数的this参数。但它不起作用。请检查中的描述 ,它说“这”不能被覆盖。是否有替代绑定函数“this”的解决方法/解决方案? 我的测试代码:如何覆盖';这';javascript中绑定函数的参数,javascript,Javascript,我有一个已经使用function.prototype.bind方法绑定的函数。不知何故,我想重写绑定函数的this参数。但它不起作用。请检查中的描述 ,它说“这”不能被覆盖。是否有替代绑定函数“this”的解决方法/解决方案? 我的测试代码: function testF() {console.log(this)} var test = testF.bind('abc'); test = test.bind('xyz'); test() // print 'abc' instead of 'x
function testF() {console.log(this)}
var test = testF.bind('abc');
test = test.bind('xyz');
test() // print 'abc' instead of 'xyz'. I'm expecting to print 'xyz'
是否有替代绑定函数“this”的解决方法/解决方案
否。如中所示,.bind
方法返回一个新的绑定函数:
[…]4.设F为(Target,thisArg,args)。
[…]
16返回F 绑定函数如下所示: 绑定函数是封装另一个函数对象的外来对象。绑定函数是可调用的(它具有
[[Call]]
内部方法,并且可能具有[[Construct]]]
内部方法)。调用绑定函数通常会导致调用其包装函数
绑定函数还有一个内部属性:
调用包装函数时,始终作为此
值传递的值
(强调矿山)
查看内部[[Call]]
方法也可以确认:
9.4.1.1[[Call]](此参数,参数列表)
当使用参数thisArgument和argumentsList(ECMAScript语言值列表)调用使用绑定函数创建的外来绑定函数对象F的[[Call]]]
内部方法时,将执行以下步骤:
[[BoundTargetFunction]]
内部插槽的值[[boundThis]]
内部插槽的值[[BoundArguments]]
内部插槽的值如您所见,
thisArgument
被完全忽略,只使用了[[BoundThis]]]
的值。设置后,无法更改[[BoundThis]]
。我要冒险不没有
绑定的整个要点是强制绑定函数始终在给定上下文中执行。bind的大致功能是:
function simpleBind(fn, context) {
return function() {
return fn.apply(context, arguments);
};
}
因此,您可以在这里清楚地看到——一个新函数实际上是在这里返回的,因此更改它的上下文对包装(绑定)函数绝对没有影响,因为它使用的是封闭函数调用中的值
我对你为什么要做这样的事情的最佳猜测是:它在适当的地方进行了黑客攻击,而不是重构,重构(几乎总是)是更好的方法。虽然我意识到这可能不在“预算之内”,但在这里你并没有得到很多选择。最好重新考虑一下你的方法,这样你就不需要做这些难看的黑客了
**这是一个简单的实现,仅用于演示要点
编辑
从@djechlin的评论中得到一些启发,我将演示一种通过使用引用类型“滥用”这个simpleBind
实现的方法(我引用了滥用,因为这实际上并没有做任何您不被允许做的事情)。在您的情况下,如果要绑定字符串(假设您对绑定值有一些控制权),您可以执行以下简单操作:
var context = {string: "abc"},
fn = function() { console.log(this.string); },
bound = fn.bind(context);
bound(); // logs 'abc'
context.string = "xyz";
bound(); // logs 'xyz'
只有当您可以更改绑定到函数的值,并使用它们是引用而不是副本的概念时,这才有用。这是标准的JS行为。一般开发答案:
//如果函数是这样声明的
let call=function(){console.log(this);}
//然后可以通过原型将函数从绑定中拉出。
call.bind({hello:'my firend'});
调用();//打印{你好:'my firend'}
call=Object.getPrototypeOf(new call()).constructor;
call();打印{window}
call=call.bind({bay:'mydarling'});
call();打印{bay:'my darling'}
缺点:您需要调用构造函数,因此调用函数体,因此可能会产生调用的副作用。例如,一个调用被计算1次,随后函数上下文中但函数外部的变量将被更改或删除。
或者抛出一个错误
如果您可以访问本机函数,则需要执行以下操作:
函数调用(){
console.log(this);
}
call=Object.assign(call.bind({hello:'myfriend'}),{owner:call});
让otherCall=Object.assign(call.bind({hello:'myfriend'}),{owner:call.owner});
otherCall();
这听起来像是一个问题-显然,提供已绑定函数的人都希望绑定它-您试图实现的最终目标是什么?这听起来更像是一个API设计问题,而不是其他任何问题。bind只是用上下文包装它,但它是用最近的上下文abc执行的。请注意,您将其绑定了两次testF.bind('abc').bind('xyz')
。第二个绑定是与外部绑定函数相关联。如果您解释一下您试图实现的总体目标,我们可能会帮助您找到一个替代解决方案。但就目前情况而言,答案是否定的。你的答案如下。我确信有一个“解决方法”,但它将涉及到访问预绑定函数。与其说这是一个解决办法,还不如说是“第一次就做对了”。如果你能控制绑定的值,你可能想看一下对我答案的编辑——否则忽略,它不会解决你的问题。在回答中,我仍然支持我之前的陈述,您可能需要重构或改变您的方法。建议添加到您的回答中:您的玩具实现遵循伪经典模式,使用闭包处理上下文<