Javascript 可以使用'bind'重新绑定回弹函数吗`

Javascript 可以使用'bind'重新绑定回弹函数吗`,javascript,Javascript,bind方法创建一个新函数,该函数在调用时将其this关键字设置为提供的值 var obj = { a: 0, b() { console.log(this.a); } } obj.b() // -> 0 var functionBound = obj.b.bind(obj) functionBound() // -> 0 functionBound.bind(null)() // -> 0 AND I expect an error here 显然,

bind
方法创建一个新函数,该函数在调用时将其
this
关键字设置为提供的值

var obj = {
  a: 0,
  b() {
    console.log(this.a);
  }
}

obj.b() // -> 0

var functionBound = obj.b.bind(obj)
functionBound() // -> 0
functionBound.bind(null)() // -> 0 AND I expect an error here
显然,我不能重新绑定一个已经被反弹的函数。但是,我找不到任何关于这种行为的文档

引用自“”

一旦使用bind将对象绑定到函数,就不能重写它。正如您在MDN文档中所看到的,规范中清楚地写着:

bind()函数创建一个新函数(绑定函数),该函数的函数体(ECMAScript 5术语中的内部调用属性)和调用它的函数(绑定函数的目标函数)相同,并且该值绑定到bind()的第一个参数,不能被重写

我在MDN文档中找不到这些。我在谷歌上对上面的引文进行了精确的全文搜索,似乎上面的答案是这种行为的唯一来源。我还试图在语言规范中找到答案,但运气不佳


我的问题是你知道这种行为吗?我在哪里可以找到关于这些行为的官方文档?

问题是Function.prototype.bind返回一个新函数,而不是相同的函数。使用不同的this参数调用绑定函数没有效果,因为绑定函数已经知道使用哪个值作为this参数

您可以将其用于绑定函数:

Function.boundOriginProp = Symbol()
Function.prototype.bindDynamic = thisArg => {
    let origin = this[Function.bindOriginProp] || this
    let bound = (...args) => origin.call(thisArg, ...args)
    bound[Function.bindOriginProp] = origin
    return bound
}
因此,您可以像这样重新绑定已绑定的函数:

let obj1 = { value: 1 }
let obj2 = { value: 2 }

function example() {
    console.log(this.value)
}

let fn1 = example.bindDynamic(obj1)
fn1() // -> 1

let fn2 = fn1.bindDynamic(obj2)
fn2() // -> 2

let fn3 = fn1.bindDynamic(null)
fn3() // -> undefined

我希望这能帮助你;)

bind方法包装原始函数并创建新的有界函数。 实际上,一个函数包装了原始函数,保持了原始函数的相同主体。 这是MDN网站中的定义:

bind()函数创建一个新的绑定函数(BF)。男朋友是一个好朋友 外来函数对象(来自ECMAScript 2015的术语),用于包装 原始函数对象。调用BF通常会导致 执行其包装函数

因此,每次调用
.bind
,都会创建一个新函数,将上下文作为第一个参数传递,将参数作为其余参数传递,但保留第一个定义的主体。 您还可以重写初始主体,并再次绑定该函数。 同时,您还可以获取以前绑定的函数并将其再次绑定到新函数。
在以下示例中,您应该看到预期的行为:

var printer = function(a) { 
    console.log(a); 
};

var printer1 = printer.bind(null, 1);
var printer2 = printer.bind(null, 2);
var printer3 = printer.bind(null, 3);

printer1();
printer2();
printer3();

printer = function(a) {
    console.log("I am a new " + a); 
};

var printer4 = printer.bind(null, 4);
printer4();

var newPrinter = function() {
    console.log('I am a new printer!');
}
printer4 = newPrinter.bind(null);
printer4();

这可能无法直接回答有关获得正式文档化的规范来验证此行为的问题,但我们可以根据MDN中提供的源代码得出结论,特别是在第节的文档中,他们提供了polyfill
bind
函数的示例

if (!Function.prototype.bind) {
  Function.prototype.bind = function(oThis) {
    if (typeof this !== 'function') {
      // closest thing possible to the ECMAScript 5
      // internal IsCallable function
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }

    var aArgs   = Array.prototype.slice.call(arguments, 1),
        fToBind = this,
        fNOP    = function() {},
        fBound  = function() {
          return fToBind.apply(this instanceof fNOP
                 ? this
                 : oThis,
                 aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    if (this.prototype) {
      // Function.prototype doesn't have a prototype property
      fNOP.prototype = this.prototype; 
    }
    fBound.prototype = new fNOP();

    return fBound;
  };
}
我们可以看到,
oThis
参数用于closure
fBound
,它是由
bind
函数最终返回的

这意味着,当您调用
bind
函数时,您将得到一个闭包函数,当调用该函数时,它将访问
其他作为原始调用
bind
中的参数提供的
自由变量

因此,无论您将绑定的
fBound
函数重新绑定多少次,此函数都已在其闭包内永远绑定到原始上下文
oThis


MDN文档还指向以供进一步参考,这似乎也与此示例相对应。

MDN是一个wiki。你引用的答案是2014年写的。有问题的短语为什么被删除了?你必须问编辑,而不是我。当前的描述同样正确,但不再关注此边缘情况。这仅仅意味着当调用绑定函数时,传入的任何thisValue都将被忽略。事实上:它表示使用bind包装的函数不可访问:
当调用绑定函数时,它调用内部方法[[Call]],并使用以下参数调用(target、boundThis、args)。其中,target是[[BoundTargetFunction]],boundThis是[[boundThis]],args是[[BoundArguments]]。
您的函数变得不可访问,无法更改,因此可能重复的函数在Chrome Canary中出现错误,在Chrome 56中在最后一行出现错误。您得到了类似ReferenceError的结果吗?这是因为如果访问不存在对象的属性,大多数浏览器都会抛出此错误。因为this参数在最后一行被设置为null,所以它会抛出这个错误,因为函数试图访问this.value,其中this.value为null^