您可以在箭头功能中绑定“ this”吗?


133

我已经在尝试ES6一段时间了,但是我遇到了一个小问题。

我真的很喜欢使用箭头功能,只要有可能,我都会使用它们。

但是,看来您无法绑定它们!

这是函数:

var f = () => console.log(this);

这是我要将功能绑定到的对象:

var o = {'a': 42};

这就是我绑定的f方式o

var fBound = f.bind(o);

然后我可以打电话给fBound

fBound();

哪个将输出此(o对象):

{'a': 42}

凉!可爱!除非它不起作用。代替输出o对象,它输出window对象。

因此,我想知道:您可以绑定箭头功能吗?(如果是这样,如何?)


我已经在Google Chrome 48和Firefox 43中测试了上面的代码,结果是相同的。


29
箭头函数的全部要点是它们使用this其父范围的。
loganfsmyth,2015年

Answers:


158

您无法重新绑定 this箭头功能。它将始终被定义为定义它的上下文。如果您需要this有意义,则应使用常规功能。

根据ECMAScript 2015规范

ArrowFunction中对参数,super,this或new.target的任何引用都必须解析为词法包围环境中的绑定。通常,这将是立即封闭函数的函数环境。


7
这个答案的第一句话是错误的。可能是因为该问题还会使绑定和绑定混淆this。两者是相关的,但不相同。this箭头函数内部始终this从封闭范围“继承” 。这是箭头功能的特征。但是您仍然可以bind使用箭头函数的所有其他参数。只是没有this
Stijn de Witt

54

为了完整起见,您可以重新绑定箭头功能,只是不能更改的含义this

bind 仍然具有函数参数的值:

((a, b, c) => {
  console.info(a, b, c) // 1, 2, 3
}).bind(undefined, 1, 2, 3)()

在这里尝试:http : //jsbin.com/motihanopi/edit?js,console


1
有没有一种方法可以检测或使用(箭头)函数绑定到的任何对象,而无需引用this(当然,这是用词法定义的)?
Florrie

3
对上下文使用参数:((context)=> {someOtherFunction.apply(context)})。bind(willBeIgnored,context)()
cvazac

13

MDN

箭头函数表达式的语法比函数表达式短,并且按词法绑定此值(不绑定其自身的this,arguments,super或new.target)。箭头函数始终是匿名的。

这意味着您无法将值绑定为所需的值this


6

多年来,js开发人员一直在努力进行上下文绑定,询问为什么this在javascript中进行了更改,多年来,由于上下文绑定以及thisjavascript和this大多数其他OOP语言中的含义之间的差异,造成了如此多的混乱。

所有这些使我问,为什么,为什么!您为什么不希望重新绑定箭头功能!专门为解决所有这些问题和混乱而避免使用bindcall任何其他方法来保留功能范围。

TL; DR

不,您无法重新绑定箭头功能。


7
首先创建了箭头函数,以提供更简洁,更快速的语法。想想λ演算。糟糕的是,OO狂热者困扰着功能性JS程序员的生活,却抓住了剥夺指定调用上下文自由的机会。
Marco Faustinelli

5
使用this不起作用。lambdas应该是arguments => output。如果您需要一些外部上下文,则将其传递。正是这种存在的存在this促进了所有OO模式在语言中的应用。没有它,您将永远不会听到术语“ javascript类”。
erich2k8

3
可以重新绑定箭头功能。只是没有this
Stijn de Witt

6

您不能用于bind更改this箭头函数内部的值。但是,您可以创建一个新的常规函数​​,其功能与旧的箭头函数相同,然后使用callbind重新绑定this照常。

我们eval在这里使用一个调用来重新创建您作为普通函数传入的箭头函数,然后使用另一个函数call来调用它this

var obj = {value: 10};
function arrowBind(context, fn) {
  let arrowFn;
  (function() {
    arrowFn = eval(fn.toString());
    arrowFn();
  }).call(context);
}
arrowBind(obj, () => {console.log(this)});


3
感谢您分享这个将箭头函数绑定到不同上下文的方法的示例!为了使答案更易于将来的读者理解,也许您可​​以对其进行编辑以描述代码的工作方式和原因?
弗洛里

4

ES6箭头功能真的可以解决JavaScript中的“ this”问题吗?

上面的链接说明,箭头功能this不会随着bind, call, apply功能。

用一个很好的例子来解释。

运行它node v4以查看“预期”行为,

this.test = "attached to the module";
var foo = { test: "attached to an object" };
foo.method = function(name, cb){ 
    // bind the value of "this" on the method 
    // to try and force it to be what you want 
    this[name] = cb.bind(this); };
foo.method("bar", () => { console.log(this.test); });
foo.bar(); 

要求您提供答案本身中的更多相关信息,可能是示例代码或问题的编辑版本
Jithin Scaria '18

//在节点v4中运行此命令,以查看“预期”行为this.test =“附加到模块”; var foo = {test:“附加到对象”}; foo.method = function(name,cb){//将方法中的“ this”值绑定// //尝试强制其成为您想要的值。[name] = cb.bind(this); }; foo.method(“ bar”,()=> {console.log(this.test);}); foo.bar();
Prithvi Raj Vuppalapati

这里有趣的是尝试一下,然后再次尝试替换foo.method('bar',()=> {console.log(this.test);}); 使用foo.method('bar',function(){console.log(this.test);}); -第一个版本记录“附加到模块”,第二个记录“附加到对象”-我真的更喜欢使用箭头功能对“ this”进行更稳定的处理。您仍然可以使用不同的模式来实现其他效果,并且结果更易于理解和预测。
Methodician'1


2

简而言之,您无法绑定箭头功能,但请继续阅读:

想象一下,您有下面的箭头功能,该功能this在控制台上显示:

const myFunc = ()=> console.log(this);

因此,解决此问题的快速方法是使用常规功能,因此只需将其更改为:

function myFunc() {console.log(this)};

然后,您可以使用bindcall或将其绑定到任何词法环境apply

const bindedFunc = myFunc.bind(this);

并在的情况下调用它bind

bindedFunc();

还有很多方法可以使用eval(),强烈不建议这样做。


function myFunc除了具有可绑定性以外,在行为上也有所不同;更接近的比赛是const myFunc = function() {...}。我也很好奇您使用eval的意思,因为这是我以前从未在这里分享过任何答案的方法-看看这样做是很有趣的,然后阅读为什么如此强烈地劝阻。
弗洛里

1

也许这个例子对你有帮助:

let bob = {
   _name: "Bob",
   _friends: ["stackoverflow"],
   printFriends:(x)=> {
      x._friends.forEach((f)=> {
         console.log(x._name + " knows " + f);
      });
   }
}

bob.printFriends = (bob.printFriends).bind(null,bob);
bob.printFriends();


gøød东西...轻度诠释
Aleks
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.