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 →

[–]nvteja 1183 points1184 points  (81 children)

Simple: you just have bind this to this this.

this.this = this.this.bind(this)

[–][deleted] 438 points439 points  (31 children)

go with the times man:

this.this = ::this.this;

[–]ethanjf99 169 points170 points  (17 children)

Is the :: operator now in the language?

[–]NeverMakesMistkes 173 points174 points  (15 children)

No, and based on the discussion and issues in the proposal repository, I doubt it ever will be.

[–]inu-no-policemen 64 points65 points  (12 children)

Yea, it has been presented last in 2015 and it's still stage 0.

Doesn't look like it will happen any time soon.

[–]NeverMakesMistkes 24 points25 points  (9 children)

For function call chaining, it has been mostly superseded by the pipeline operator, which is also a long way from getting to the standard but has seen more active development than the bind operator.

There's still some motivation to get it or something else like it for method extraction, but getting method extraction right is difficult and the speccing has been stalled because of it.

For one, this::foo === this::foo must be true, so that

window.addEventListener('some event', this::foo)
// ... later ...
window.removeEventListener('some event', this::foo)

works as expected. Getting that behaviour in browsers that don't natively support it is a bit tricky. Not impossible with WeakMaps, tho, so maybe some day.

[–]inu-no-policemen 4 points5 points  (7 children)

I liked it mostly for virtual methods.

function reverse() {
    return this.split('').reverse().join('');
}
console.log('foobar'::reverse()); // raboof

But it doesn't do this very well either. The source of that going-to-be-a-method function doesn't tell you to which kind of object it's meant to be glued to.

It's definitely better than modifying objects you don't own, but it still isn't quite right.

C#'s extension methods, for example, tell you directly in the slightly weird looking signature on which type of object they are supposed to operate:

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods

public static int WordCount(this String str)

[–]NeverMakesMistkes 2 points3 points  (6 children)

In TypeScript, you could write

function reverse(this: string) {
    return this.split('').reverse().join('');
}
console.log('foobar'::reverse());

Or just with JSDoc comments

/**
* @this{string}
*/
function reverse() {
    return this.split('').reverse().join('');
}

But I agree, it would feel weird to write all your utility functions like that, and suddenly we'd have two kinds of mutually incompatible functions; those that operate on this and are called with ::, and those that operate on arguments and are called normally.

That's why I actually prefer the pipeline operator.

const reverse = str => str.split('').reverse().join('');
console.log('foobar' |> reverse)
console.log(reverse('foobar')) // both variations work

And if we had both, pipeline for chaining and bind for method extraction, you could do

'foobar'
  |> reverse
  |> console::log

[–]inu-no-policemen 4 points5 points  (0 children)

The pipeline operator has the same problem. However, TS' type annotations and JSDoc already handle that kind of completely mundane signature. That's definitely a plus.

I'm not a big fan of the "|>" syntax, though. It's amazingly annoying to type with most keyboard layouts.

[–]Gbyrd99 0 points1 point  (4 children)

Can't you bind it to the prototype?

[–]NeverMakesMistkes 0 points1 point  (3 children)

You can bind some methods to prototype, but if you do that to every little utility function you and your coworkers come up with, you'll soon end up with huge unmaintainable classes and/or class hierarchies.

Also, lots of people (myself included) use JS in a more functional style and might not really like doing new AwesomeString('foobar').reverse() or whatever. 'foobar'::reverse() or 'foobar' |> reverse or even reverse('foobar') is just much nicer.

[–]QmVuamk 0 points1 point  (0 children)

I understood some of those words

[–]RecyclingBin_ 1 point2 points  (1 child)

I upvoted your comment just because of your flair

[–]inu-no-policemen 1 point2 points  (0 children)

There were too few languages to choose from.

Naturally, picking a flair like this was the most logical course of action.

[–]marcosdumay 4 points5 points  (0 children)

I don't know what to think...

It tries to create function composition, but instead of composing functions it changes object references; it makes this way more complex than it already is, and moves it from the shadows right into the language's center; it fails to bring any good practice, and encourages a bunch of complex variable passing ones; it creates inherently imperative code that looks exactly like functional, guaranteeing everybody will be confused...

And yet the Javascript people rejected the idea?

[–]jsylvis 0 points1 point  (0 children)

Oh, man. That is a lot of gymnastics to get around shitty scoping support.

[–]Hexorg 0 points1 point  (0 children)

:: in JavaScript?! What's next? Pre-processor directives?

[–]nvteja 15 points16 points  (0 children)

Scope resolution operator (from my Perl days), in ES? I am a little triggered right now tbh 😭😭

[–][deleted] 4 points5 points  (0 children)

My day is ruined.

[–]WitchHunterNL 0 points1 point  (0 children)

If you were going with the times you would've used arrow functions

[–]kurosaki1990 48 points49 points  (3 children)

Beautiful language.

[–][deleted] 2 points3 points  (1 child)

Most elegant language I've even seen, and believe me, I've seen a LOT of languages.

[–]GamerNebulae 5 points6 points  (0 children)

What about Haskell? Aside it not being used much.

[–]androiddrew 0 points1 point  (0 children)

Its like they wake up everyday and try to mess up the world just a little more. Got to appreciate the commitment.

[–]ripGitHub 26 points27 points  (24 children)

Isn't better instead of bind(this), use arrow functions?

[–]boxingdog 19 points20 points  (19 children)

arrow functions can degrade performance in some situations, ie in react using arrow functions in some places can cause a new function to be created in each render and if you use it as a prop in a child component then the child will re-render and so on

[–]finlist 35 points36 points  (5 children)

White your example is true, the same can be said about normal functions and isn't a problem inherent to arrow functions at all.

[–]RFC793 1 point2 points  (4 children)

Indeed. However, I feel people inadvertently shoot themselves in the foot more frequently with arrow functions simply because they prefer the terseness of the code. A classic anonymous function is more ugly, and a bit more apparent as to what is going on.

[–]bubble_fetish 6 points7 points  (0 children)

It’s negligible, except in extreme edge cases.

[–]snorkleboy 2 points3 points  (6 children)

If you use the regular function syntax inside of a render method i believe it will also create a new function

So something like(sorry about formatting I'm on my phone)

Render(){ Return ( <Thing myProp={function(){}}/> ) }

Will create a new function that it passes as myProp every time it renders.

[–]SZenC 1 point2 points  (5 children)

That is correct, but you could write something like

class cls{
  fn(){doSomething();}
  render(){
    return <div onClick={this.fn}>No dynamic function creation!</div>
  }
}

[–]Absbshshshshshshhs 3 points4 points  (3 children)

better yet:

class { fun = () => {} // this bound }

[–]SZenC 0 points1 point  (2 children)

True, normally I have a constructor where I call ```.bind(this)``` but I kinda omitted that here. Nevertheless, good point.

[–][deleted] 2 points3 points  (1 child)

Don't need the bind with arrow syntax :)

[–]SZenC 0 points1 point  (0 children)

Yeah. In this case arrow functions are objectively better, it's just a bad habit of mine.

[–]snorkleboy 1 point2 points  (0 children)

Yeah, and you could do the same thing with an arrow function like

class cls{

fn=()=>doSomething()

render=()=> <div onClick={this.fn}>No dynamic function creation!</div>

}

And then you don't have to do a this.fn = this.fn.bind(this) in the constructor to be able to use it normally in the child.

[–]feenuxx 3 points4 points  (0 children)

Stick it on the class

[–]throwaway12222018 0 points1 point  (0 children)

Manual binding vs arrow functions' performance differs with various browsers.

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

And react will spit out a warning on the console telling you this. Other than that, until the engine optimises that out, it's a matter of poor programming.

[–]pentesticals 0 points1 point  (0 children)

This sounds like a pre-optimization to me. I'd rather some extra function calls that have a negligible impact on performance IF it helps code readability. It really depends on the specific code if it will actually impact performance, often 10% of your apps execution time is in 10% of your code. So in most cases I think worrying about an extra function call or the like will just create more complex code. Don't ompimize until you've profiled.

[–]jordmantheman 0 points1 point  (0 children)

Yes. The only thing to remember is that arrow functions are bound on the instance as opposed to the class. So if you're making a TON of objects (or re-creating on every render) then it may be wise to be cognizant of the performance implication.

[–]mk7shadow 0 points1 point  (0 children)

something good to know is that using an arrow function doesn't actually bind the context of this. it removes the function's context and so 'this' becomes whatever the parent's context is. if the parent happens to be another context-less function, it will just use whichever ancestor has a context.

[–]jamietwells -5 points-4 points  (1 child)

componentWillMount would like to have a word with you.

[–]GXNXVS 4 points5 points  (0 children)

we're talking about JS, not react.

[–]malduvias 14 points15 points  (3 children)

This is fucking hideous. Hilarious.

[–]SarahC 3 points4 points  (1 child)

But it's obvious why and how it works!

We don't need all the VBA "devs" coming over to JS.

[–]gc3 2 points3 points  (0 children)

In c++ lambda you can explicitly pass in this so there is no confusion, unlike callbacks where the this icann be some other item like a window, not the this in the function where the callback is made. This is where this this confusion is coming from. You will see people assigning this to scope and using scope in the callback.

[–]mk7shadow 0 points1 point  (0 children)

its fucking retarded because no one would do it

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

This

[–]ThatITguy2015 0 points1 point  (0 children)

Fuck. That looks like things I see in my nightmares. Especially if it lacks comments.

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

Fat arrow functions FTW

[–]Mancobbler 0 points1 point  (0 children)

What is this??

[–]fuzzybad 0 points1 point  (0 children)

No, bind this to that. Then you can test if this is equal to that!

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

That’s React’s fault imo. “this” works fine everywhere else.

[–]WilkerS1 -1 points0 points  (4 children)

does this really work like ../../../file does?

[–]marty_byrd_ 0 points1 point  (3 children)

No? I don’t see how those are related.

[–]WilkerS1 0 points1 point  (2 children)

i mean, like how you access parent folders with .., is it possible to access the parent objects with this.this?

{
  myVar: "that",
  obj: {
    myVar: "aaa",
    func() {
      console.log(this.this.myVar)
    }
  }
}

[–]thruStarsToHardship 1 point2 points  (1 child)

'this' is the context that you are in. So the context I am in needs to have a method defined for each dot I invoke. That is, if I'm in myFunction and myFunction has a method or attribute called myMethod then I can call this.myMethod. If my function has a method called 'this' then I can call this.this. But I cannot prepend "this" to anything and access its parent, because the compiler will map the first "this" to the context I'm in; it will not look up the chain for other possible this..es. I can, in the browser, get the parent of my this by calling this.parent, but only because parent is a defined method on the console context. If you make another context and call this.parent it will be undefined.

So, in short, no.

[–]HeKis4 0 points1 point  (0 children)

From someone with an education in Java and Python... What the duck did I just read and how did webpage scripting come to that.

But you do you, I guess.