Can you bind arrow functions?

2019-01-01 11:54发布

问题:

I\'ve been experimenting with ES6 for a while now, and I\'ve just come to a slight problem.

I really like using arrow functions, and whenever I can, I use them.

However, it would appear that you can\'t bind them!

Here is the function:

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

Here is the object I want to bind the function to:

var o = {\'a\': 42};

And here is how I would bind f to o:

var fBound = f.bind(o);

And then I can just call fBound:

fBound();

Which will output this (the o object):

{\'a\': 42}

Cool! Lovely! Except that it doesn\'t work. Instead of outputting the o object, it outputs the window object.

So I\'d like to know: can you bind arrow functions? (And if so, how?)


I\'ve tested the code above in Google Chrome 48 and Firefox 43, and the result is the same.

回答1:

You cannot \"rebind\" an arrow function. It will always be called with the context in which it was defined. Just use a normal function.

From the ECMAScript 2015 Spec:

Any reference to arguments, super, this, or new.target within an ArrowFunction must resolve to a binding in a lexically enclosing environment. Typically this will be the Function Environment of an immediately enclosing function.



回答2:

To be complete, you can re-bind arrow functions, you just can\'t change the meaning of this.

bind still has value for function arguments:

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

Try it here: http://jsbin.com/motihanopi/edit?js,console



回答3:

From the MDN:

An arrow function expression has a shorter syntax compared to function expressions and lexically binds the this value (does not bind its own this, arguments, super, or new.target). Arrow functions are always anonymous.

This means you cannot bind a value to it like you want.



回答4:

For years, js developers struggled with context binding, asked why this changed in javascript, so much confusion over the years due to context binding and the difference between the meaning of this in javascript and this in most of the other OOP languages.

All this leads me to ask, why, why! why would you wan\'t to rebind an arrow function! Those where created specially to solve all this issues and confusions and avoid having to use bind or call or whatever other way to preserve the scope of the function.

TL;DR

No, you cannot rebind arrow functions.



回答5:

I asked the same question a couple days ago.

You cannot bind a value since the this is already binded.

Binding different this scope to ES6 => function operator



回答6:

Do ES6 Arrow Functions Really Solve “this” In JavaScript

The above link explains that arrow functions this doesn\'t change with bind, call, apply functions.

It is explained with a very nice example.

run this in node v4 to see the \"expected\" behavior,

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(); 


回答7:

Maybe this example help to you :

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();



回答8:

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