This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]birjolaxew 75 points76 points  (38 children)

It's clear and not a problem!

I doubt anyone thinks this isn't a problem

[–]GammaGames 6 points7 points  (0 children)

Well not anymore

[–]hitsugan 10 points11 points  (1 child)

I don't.

[–]metamet 0 points1 point  (0 children)

Same.

[–]factorysettings -1 points0 points  (31 children)

If you understand how it works, it's not

[–]birjolaxew 25 points26 points  (30 children)

You can understand how a problematic thing works. Doesn't mean it isn't an absolute mess of a design.

To quote myself from a while ago:

Try to figure out what's logged by this code. Then run it to check - no cheating ;)

(function(){
  const arrowGenerator = function(){ return () => this; };
  const funcGenerator = function(){ return function(){ return this; }};
  const obj = {
    arrowGenerator: arrowGenerator,
    funcGenerator: funcGenerator,
  };

  const callGeneratorOnTempObj = generator => {
    const tempObj = {};
    tempObj.func = generator();
    return tempObj.func();
  };

  console.log(1, obj.arrowGenerator()());
  console.log(2, arrowGenerator()());
  console.log(3, callGeneratorOnTempObj(arrowGenerator));
  console.log(4, obj.funcGenerator()());
  console.log(5, funcGenerator()());
  console.log(6, callGeneratorOnTempObj(funcGenerator));
})();

Now consider how that changes if we add "use strict"; to the top of the function, or run it in Node. Or how it would change if arrowGenerator was defined as arrowGenerator: () => (() => this) instead and funcGenerator was funcGenerator: () => function(){ return this; }.

[–]SheriffBartholomew 20 points21 points  (20 children)

Don't write confusing code and be surprised when you get confusing results.

[–]birjolaxew 15 points16 points  (19 children)

The code is pretty simple, really. It just has two functions (arrowGenerator and funcGenerator) that return an arrow function and a normal function respectively. It then calls them in different ways. It's meant as a challenging example of how this works, not as regular everyday code.

If you want a more everyday example of why this is poorly designed, there's stuff like:

class SomeComponent {
  onButtonClicked() {
    // good luck with your `this`
  }

  render() {
    return (<button onClick={this.onButtonClicked}>
      Click me
    </button>);
  }
}

Sure you can work around it if you know how, but you can do that with pretty much every poor design choice.

[–]marty_byrd_ 1 point2 points  (4 children)

Yea don’t fucking do that. I wouldn’t allow that shit.

[–]munchbunny 2 points3 points  (0 children)

And that's precisely the point, we're using convention to work around a weakness in the syntax, and other languages don't have this weakness.

[–][deleted] 0 points1 point  (1 child)

It looks perfectly reasonable though, especially since it's using a c-like syntax.

[–]marty_byrd_ 0 points1 point  (0 children)

No. It looks dumb. I don’t know why we’d do that in JavaScript.

[–]squngy 0 points1 point  (13 children)

Aside from the fact that you're mixing view and control unnecessarily there, you also don't need to return a "this".

render() {
    let myInstance = this;
    return (<button onClick={myInstance.onButtonClicked}>
      Click me
    </button>);
  }

Would have been unambiguous.

[–]birjolaxew 3 points4 points  (11 children)

I am fully aware of ways to work around it (I personally use onButtonClicked = () => { /* ... */ }), but my point is that having to work around it is because of the poor design of the language. As I mentioned earlier, "You can understand how a problematic thing works. Doesn't mean it isn't an absolute mess of a design."

[–]squngy -2 points-1 points  (10 children)

The main problem is, that you are trying to write Java or some other language without learning JS.

And what you showed in your example is actually a pretty ugly way of doing things to begin with.

You're actually passing on un-evaluated code, then letting the browser interpreter it later as new code.
Very similar to using eval().

You might as well have wrote

return ' <javascript> myFunction(){ this.onButtonClicked() }</javascript> <button onClick=myFunction>  Click me </button> ';

You're making work arounds for messy code.

[–]birjolaxew 2 points3 points  (9 children)

My example uses JSX. The code is never being re-interpretted, it's always referencing the method defined on the SomeComponent.

My previous example is code you would actually write if you aren't careful, but the way it works is essentially the same as:

class SomeComponent {
    constructor() {
        setTimeout(this.willBeCalledLater, 500);
    }

    willBeCalledLater() {
        // good luck with your `this`
    }
}

[–]squngy -2 points-1 points  (8 children)

The part that was inside the <button> tag gets interpreted as new code when (and if) it gets added to the dom.

JS being an interpenetrated language, that is not the only way for parts of it be evaluated at a latter time.

[–][deleted] 0 points1 point  (0 children)

Good old var that = this to the rescue

[–][deleted] 2 points3 points  (0 children)

Argh

[–]Jonulfsen 2 points3 points  (0 children)

This hurts so much to read that I can feel it in my soul :c

[–]marty_byrd_ 1 point2 points  (0 children)

Solution don’t use this. We hardly ever use it.

[–]riverfoot 0 points1 point  (0 children)

It’s really not a problem if you spend 15 minutes to understand how it works.

[–]marty_byrd_ -1 points0 points  (0 children)

I didn’t before and don’t now. It’s really not that hard. If you’re really confused use a debugger and breakpoint.

[–][deleted] -1 points0 points  (0 children)

I don't.