我有一个已经使用Function.prototype.bind方法绑定的函数。不知何故,我想覆盖绑定函数的this参数。但它不起作用。检查https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind中的说明 ,它说“这个”不能覆盖。是否有任何解决方法/解决方案来覆盖'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'
答案 0 :(得分:11)
是否有任何解决方法/解决方案可以覆盖'这个'绑定函数?
没有。正如您在spec中看到的那样,.bind
方法返回一个新的绑定函数:
[...]
4.让 F 为BoundFunctionCreate(Target,thisArg,args) [...]
16.返回 F 。
绑定函数为described:
绑定函数是包装另一个函数对象的异域对象。绑定函数是可调用的(它具有
[[Call]]
内部方法,并且可以具有[[Construct]]
内部方法)。调用绑定函数通常会调用其包装函数。
绑定函数还具有内部[[BoundThis]]
属性:
在调用包装函数时,始终的值作为
this
值传递。
(强调我的)
查看内部[[Call]]
方法也证实了这一点:
9.4.1.1 [[Call]](thisArgument,argumentsList)
当使用bind函数创建的外来绑定函数对象{em> F 的
[[Call]]
内部方法时,使用参数 thisArgument 和< em> argumentsList ,ECMAScript语言值列表,采取以下步骤:
- 让目标为 F 的
[[BoundTargetFunction]]
内部广告位的值。- 让 boundThis 为 F 的
[[BoundThis]]
内部广告位的值。- 让 boundArgs 为 F 的
[[BoundArguments]]
内部广告位的值。- 让 args 成为一个新列表,其中包含与列表 boundArgs 相同的值,其顺序与列表 argumentsList 以相同的顺序。
- 返回致电(目标, boundThis , args )。
醇>
如您所见,thisArgument
完全被忽略,只使用[[BoundThis]]
的值。设置后无法更改[[BoundThis]]
。
答案 1 :(得分:3)
我会冒险没有没有。
绑定的整个要点是强制绑定函数始终使用给定的上下文执行。关于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行为的副本时,这才有用。
答案 2 :(得分:0)
总体发展的答案
//if the function is declared like this
let call=function(){console.log(this);}
// then you can pull the function out of bind through the prototype.
call.bind({hello:'my firend'});
call();// print {hello:'my firend'}
call= Object.getPrototypeOf(new call()).constructor;
call(); print {window}
call=call.bind({bay:'my darling'});
call(); print {bay:'my darling'}
缺点:您需要调用构造函数,其结果是调用函数的主体,因此可能会对调用产生副作用。例如,调用被计算了1次,随后在函数上下文中但在函数范围之外的变量将被更改或删除。 或抛出错误。
如果您有权访问本机功能,则需要执行以下操作:
function call(){
console.log(this);
}
call=Object.assign(call.bind({hello:'my friend'}),{owner:call});
let otherCall=Object.assign(call.bind({hello:'my friend'}),{owner:call.owner});
otherCall();