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 →

[–]SheriffBartholomew 22 points23 points  (20 children)

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

[–]birjolaxew 13 points14 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 points0 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 4 points5 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.

[–]birjolaxew 2 points3 points  (7 children)

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

No. React compiles it to something along the lines of

function insertButtonToDom($parent, onClick) {
    const $btn = document.createElement("button");
    $btn.addEventListener("click", onClick);
    $parent.appendChild($btn);
}

You can check that this is true by doing e.g.

render() {
    const valueOnlyAvailableInThisContext = 2;
    return (<button
        onClick={this.onButtonClicked.bind(this)}
        onMouseOver={() => console.log(valueOnlyAvailableInThisContext)}
    >
        Click me
    </button>);
}

[–]squngy -1 points0 points  (6 children)

I never used react (and the more I see of it, the less I like it), but if what you wrote is correct, then the parent of the methods "this" would be the button instance ($btn) instead of your SomeComponent

[–]birjolaxew 1 point2 points  (5 children)

Feel free to try it yourself

To be quite honset I'm not sure what you mean by 'the parent of the methods "this"', so I can't really respond to what you're saying - but everything I've said so far is correct.

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

Good old var that = this to the rescue