如何覆盖';这';javascript中绑定函数的参数

如何覆盖';这';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.prototype.bind方法绑定的函数。不知何故,我想重写绑定函数的this参数。但它不起作用。请检查中的描述 ,它说“这”不能被覆盖。是否有替代绑定函数“this”的解决方法/解决方案? 我的测试代码:

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]]]
内部方法时,将执行以下步骤:

  • 让target为F的
    [[BoundTargetFunction]]
    内部插槽的值
  • 设boundThis为F的
    [[boundThis]]
    内部插槽的值
  • 让boundArgs为F的
    [[BoundArguments]]
    内部插槽的值
  • 设args是一个新列表,其中包含与列表边界args相同的值,顺序相同,后跟与列表参数列表相同的值,顺序相同
  • 返回调用(目标、边界、参数)

  • 如您所见,
    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')
    。第二个绑定是与外部绑定函数相关联。如果您解释一下您试图实现的总体目标,我们可能会帮助您找到一个替代解决方案。但就目前情况而言,答案是否定的。你的答案如下。我确信有一个“解决方法”,但它将涉及到访问预绑定函数。与其说这是一个解决办法,还不如说是“第一次就做对了”。如果你能控制绑定的值,你可能想看一下对我答案的编辑——否则忽略,它不会解决你的问题。在回答中,我仍然支持我之前的陈述,您可能需要重构或改变您的方法。建议添加到您的回答中:您的玩具实现遵循伪经典模式,使用闭包处理
    上下文<