5

Since functions are given "global context" when not accessed as a property of an object [1], the following has the same quirk:

const foo = ({bar}) => {
  bar(); // this === window
}

because it's just syntactic sugar for:

const foo = (x) => {
  var bar = x.bar;
  bar();
}

which seems slightly counter-intuitive to me since I now have to re-bind or forgo the sugar.

Is there a way to change this behaviour so that the context isn't changed (besides explicitly setting it via .apply/call/bind)? Are there any plans/proposals for standards to be implemented for it?

[1] Javascript lost context when assigned to other variable

Community
  • 1
  • 1
reoh
  • 282
  • 5
  • 12
  • There is a proposal for something relevant https://github.com/zenparsing/es-function-bind but it's stage-0. – zerkms Jul 21 '16 at 00:15
  • 4
    That's not a quirk, that's an integral part of the language design. The sugar is there to make things easier for you, not to do the thinking. When passing a callback-function, it's unusual that it needs to be called in a specific context. Even if it's passed as a property (named "bar" or maybe "success"/"fail") on some config-object. On the other hand, if you pass an instance of some class, and need to call a method on that instance, well that's a totally different approach/use-case. And it's up to you to implement either one or the other. This sugar just helps at implementing the former – Thomas Jul 21 '16 at 00:34
  • What do you want `this` to be? – aray12 Jul 21 '16 at 01:11
  • 1
    @zerkms: The suggestions to integrate the `::` operator in destructuring were dropped however. – Bergi Jul 21 '16 at 06:07
  • @aray12 For the context for `bar` to be `x` – reoh Jul 21 '16 at 13:17

2 Answers2

2

Well, you answered your own question. If you are taking an Object as argument, then any function you pass as a property will already be a method, thus loosing context, regardless of what the syntax looks like.

What you can do is call the bound function from inside the argument's method:

const argumentContainingBar = {
  bar: () => { originallyBoundFunction() }
}

Now you can foo(argumentContainingBar) without loosing context.

Hugo Silva
  • 6,748
  • 3
  • 25
  • 42
1

If you don't want to use call/apply, then your only choice is not to assign the property to a variable.

Seriously, don't use destructuring for methods. It wasn't made for that.

Are there any plans/proposals for standards to be implemented for it?

There was a suggestion in the function-bind proposal, but it was not pursued further.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • `function foo({ ::doA, ::doC }) {` --- woah, with such a pace in 3 years ES will take over haskell in terms of number of "funny" characters/constructs used in the language. – zerkms Jul 21 '16 at 09:59
  • @zerkms: That might be one reason why it's been dropped :-) – Bergi Jul 21 '16 at 10:00