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 more arguments of an already bound function in Javascript”
将对象绑定到具有bind的函数后,您无法覆盖它。正如你在MDN文档中看到的那样,它清楚地写在规范中:
bind()函数创建一个新函数(一个绑定函数),它具有相同的函数体(ECMAScript 5术语中的内部调用属性),因为它被调用的函数(绑定函数的目标函数)具有此值绑定到bind()的第一个参数,它不能被覆盖。
我在MDN文档中找不到这些内容。我在Google上面的引文上做了一个精确的全文搜索,似乎上面的SO答案是这种行为的唯一来源。我也试着在语言规范中找到一个没有运气的答案。
我的问题是你知道这种行为吗?我在哪里可以找到关于这些行为的官方文件?
答案 0 :(得分:4)
这可能无法直接回答有关获得正式记录的规范验证此行为的问题,但我们的结论可以基于MDN中提供的源代码,特别是Function.prototype.bind()的文档,在{{3它们提供了一个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
参数用在闭包fBound
中,这是bind
函数最终返回的那个。
这意味着当你调用bind
函数时,你得到一个闭包函数,当被调用时,它会访问oThis
自由变量作为{{1}原始调用中的参数提供的}。
因此,重新绑定绑定bind
函数多少次并不重要,此函数已经永久绑定到其闭包中的原始上下文fBound
。
MDN文档还指向Polyfill以供进一步参考,这似乎也与此示例相对应。
答案 1 :(得分:1)
问题是Function.prototype.bind返回一个NEW函数而不是相同的函数。使用不同的this-argument调用绑定函数无效,因为绑定函数已经知道要将哪个值用作this-argument。
您可以使用它来绑定您的功能:
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
我希望这可以帮到你;)
答案 2 :(得分:0)
bind方法包装原始函数并创建一个新的Bounded函数。 实际上,包含原始函数的函数保持原始函数的相同主体。 这是MDN网站上的定义:
bind()函数创建一个新的绑定函数(BF)。 BF是一个 外来的功能对象(来自ECMAScript 2015的术语)包装了 原始功能对象。调用BF通常会导致 执行包装函数。
因此,每次调用.bind
时,都会创建一个新函数,将上下文作为第一个参数传递,将args作为其余参数传递,但保留第一个定义的主体。
您还可以覆盖初始正文,然后再次绑定该函数。
同时,您还可以使用先前有界的函数并将其再次绑定到新函数
在以下示例中,您应该看到预期的行为:
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();