News for hackers. Stuff that matters.
Re:Is there any code in Firefox (as of 2020) that comes from... by goto11 on Saturday March 28, 2020 @10:46AM (#22711422)
It has nothing to do with dynamic binding. "this" has lexical scope just like regular parameters. I agree 'this' is confusing, but you are making it sound more mysterious than it is. It is just some syntactic sugar around an implicit first parameter.
Re:Is there any code in Firefox (as of 2020) that comes from... by DonHopkins on Saturday March 28, 2020 @02:27PM (#22713173)
Nope. "this" is formally defined as a keyword in the JavaScript syntax, not a variable, not a property name, not an identifier, and not syntactic sugar, since there is no source level transformation you can make that behaves the same (like with C++, the way CFront translated "this" into an actual first parameter). JavaScript's "this" is magic, that's why it has to be a keyword, not a variable.

It looks like a variable, and it kind of but not really behaves like an implicit first parameter in some circumstances, but that's not really what's going on at all. And that is the danger, and source of misunderstanding and bugs: it looks like something that it's not.

For one thing, you can't assign to "this" like a variable. For another thing, "this" doesn't show up in "arguments" (which is also magic). If you think "this" is not mysterious and just a normal but implicit argument, you don't really understand it.

Which is my point: "this" is such a terribly designed language feature that even experienced JavaScript programmers misunderstand it, and it causes subtle hard to find bugs, even for experienced JavaScript developers. It's not just mysterious, it's dangerous.

https://books.google.nl/books?id=4RChxt67lvwC&pg=PA169&lpg=P...

>JavaScript: The Definitive Guide

>Note that this is a keyword, not a variable or property name. JavaScript syntax does not allow you to assign a value to this.

>Unlike variables, the this keyword does not have a scope, and nested functions do not inherit the this value of their caller. [...]

Here is how "this" is explicitly defined as a keyword in the JavaScript BNF grammer, in this example as the very first option of PrimaryExpression. Definitely not a variable or Identifier. Quite magic. No other "variable" name is defined as a top level PrimaryExpression. "this" is very special.

https://tomcopeland.blogs.com/EcmaScript.html

    PrimaryExpression ::= "this"
                        | ObjectLiteral
                        | ( "(" Expression ")" )
                        | Identifier
                        | ArrayLiteral
                        | Literal
You can even ask devtools for its opinion:

    >var this = 1;
    VM2547:1 Uncaught SyntaxError: Unexpected token 'this'
Re:Is there any code in Firefox (as of 2020) that comes from... by minitech on Sunday March 29, 2020 @11:18PM (#22724932)
When people say it behaves like an implicit first parameter, they’re not claiming it literally is a parameter/variable. Of course it’s a keyword. Of course you can’t assign to it. You’re writing long rebuttals to made up arguments.

You’re also misusing terminology by saying `this` is “dynamically scoped” (it does not have dynamic scope[1], that would be terrible) when documents you’re quoting say “dynamically bound”. The difference is important, which is why three people have corrected you on that now.

[1] https://en.wikipedia.org/wiki/Scope_(computer_science)#Dynam...

Re:Is there any code in Firefox (as of 2020) that comes from... by DonHopkins on Monday March 30, 2020 @04:21PM (#22731902)
So do you agree with goto8 when he says ""this" has lexical scope just like regular parameters" and "Nevertheless, scope wise it behaves like an implicit parameter with lexical scope"?

Explain just how "this" is lexically scoped, what "lexically scoped" means, and then explain why they had to add fat arrow to the language, if "this" is "just like regular parameters", please?

If "this" is lexically scoped, then why can call and apply change it at runtime?

And how do explain this stackexchange discussion, which directly addresses and answers the question? The detailed answer "yes" got five votes and was accepted. The other answer "no" got one vote and was not accepted. What's your answer?

https://softwareengineering.stackexchange.com/questions/3961...

Question> Is `this` in JavaScript an example of dynamic scoping?

Accepted Answer> To be clear, JavaScript does not, in fact, have dynamic scope. It has lexical scope. Plain and simple. But the this mechanism is kind of like dynamic scope.

>The key contrast: lexical scope is write-time, whereas dynamic scope (and this!) are runtime. Lexical scope cares where a function was declared, but dynamic scope cares where a function was called from.

>Finally: this cares how a function was called, which shows how closely related the this mechanism is to the idea of dynamic scoping.

And you ironically wrote:

>(it does not have dynamic scope[1], that would be terrible)

Whatever you call it and however you define dynamic scope, the dynamic way "this" behaves IS terrible, and undeniably causes lots of easy to make, hard to diagnose bugs. That is why Brendan Eich called it a "footgun". That was my point, and that was why they had to add fat arrow to the language.

Re:Is there any code in Firefox (as of 2020) that comes from... by goto11 on Monday March 30, 2020 @05:52PM (#22732615)
Unfortunately, people voting on StackOverflow are not always correct. If you want the correct answer without guessing, you can check the ECMAScript spec itself:

8.3.2 GetThisEnvironment ( )

The abstract operation GetThisEnvironment finds the Environment Record that currently supplies the binding of the keyword this. GetThisEnvironment performs the following steps:

    1. Let lex be the running execution context’s LexicalEnvironment.
    2. Repeat
        a. Let envRec be lex’s EnvironmentRecord.
        b. Let exists be envRec.HasThisBinding().
        c. If exists is true, return envRec.
        d. Let outer be the value of lex’s outer environment reference.
        e. Let lex be outer.
NOTE The loop in step 2 will always terminate because the list of environments always ends with the global environment which has a this binding.

Source: http://www.ecma-international.org/ecma-262/6.0/#sec-getthise...

This is pretty unambiguous. The "this" binding is resolved in the lexical scope, not the dynamic scope.

Re:Is there any code in Firefox (as of 2020) that comes from... by minitech on Monday March 30, 2020 @07:51PM (#22733429)
> So do you agree with [goto11 that] ""this" has lexical scope just like regular parameters" and "Nevertheless, scope wise it behaves like an implicit parameter with lexical scope"?

Yes.

> Explain just how "this" is lexically scoped, what "lexically scoped" means, and then explain why they had to add fat arrow to the language, if "this" is "just like regular parameters", please?

`this` is lexically scoped* because the function it belongs to is determined by where it appears in the code.

Fat arrow was added to the language with this difference because it’s useful to have a function without its own `this`.

> If "this" is lexically scoped, then why can call and apply change it at runtime?

It’s always set at call time. Not a matter of scope. (Parameters: also have values determined at call time, also lexically scoped.)

  function a() { return this; }
  let obj = {a};
  obj.a() === obj
> And how do explain this stackexchange discussion, which directly addresses and answers the question? The detailed answer "yes" got five votes and was accepted. The other answer "no" got one vote and was not accepted. What's your answer?

The answer is wrong despite its votes. The comment on it by JacquesB is correct: “This is confusing values and variables. this cares cares how a function is called the same way parameters care how a function is called - they get their value at runtime when the function is called. But the scope of all variables (including this) is lexical and not dynamic.”

> Whatever you call it and however you define dynamic scope, the dynamic way "this" behaves IS terrible, and undeniably causes lots of easy to make, hard to diagnose bugs. That is why Brendan Eich called it a "footgun". That was my point, and that was why they had to add fat arrow to the language.

I disagree, but am mostly here to argue against objectively wrong information rather than opinions.

* in contrast to dynamically scoped. In JavaScript it’s also common to use “lexical scope” in contrast to “function scope” to distinguish `let`/`const` vs. `var`. In the JavaScript spec, the lexical thisMode refers to where the (arrow) function appears, not the position of the `this`.

Re:Is there any code in Firefox (as of 2020) that comes from... by goto11 on Saturday March 28, 2020 @03:25PM (#22713679)
Nevertheless, scope wise it behaves like an implicit parameter with lexical scope. It just muddies the issue to talk about dynamic scope.
Re:Is there any code in Firefox (as of 2020) that comes from... by DonHopkins on Sunday March 29, 2020 @08:42PM (#22724173)
Dude or dudess, "this" absolutely does not behave in any way like it is lexically scoped, in any sense of the term.

Reality check: Are we even talking about the same language? I'm talking about JavaScript. Which language are you talking about, C++? If you're not talking about JavaScript, then you replied to the wrong comment. Or are you just trolling and gaslighting, because you were offended by the Trump reference? I'll give you the benefit of the doubt that you're also referring to JavaScript, and that you sincerely believe what you say, because you need to change your beliefs.

Please go read any elementary JavaScript tutorial, or any of the thousands of blog posts by people who got screwed by accidentally mis-understanding for a moment and mistakenly thinking that "this" was lexically scoped, then got burnt, but learned from the experience, and wanted to share with everyone else what they learned by shooting themselves with an "oft-fired footgun": "this" is dynamically scoped, and changes meaning at runtime, regardless of the surrounding lexical environment in which it was defined, UNLESS you use fat arrow functions, which were specifically designed to work around that problem.

If "this" behaved like an implicit parameter with lexical scope, then why did they bother adding fat arrow functions to the language as an afterthought, to work around the problem you don't seem to believe exists?

One more time, I will quote the rationale section of Brendan Eich's fat arrow proposal:

https://tc39wiki.calculist.org/es6/arrow-functions/

>"dynamic this binding is an oft-fired footgun" -Brendan Eich, ES6 Arrow Functions Proposal

If you're right, then Brendan Eich, Douglas Crockford, Anders Hejlsberg, many other expert designers and programmers of JavaScript and TypeScript, and a whole lot of other people, are also extremely confused:

https://www.forumone.com/ideas/typescript-application-scale-...

>TypeScript borrows some features from the upcoming ECMAScript 6 specification, too. There is convenience syntax for day-to-day programming tasks, such as the arrow function, borrowed from CoffeeScript. The arrow function, which looks like this: (foo, bar) => baz, is shorthand notation for (function (foo, bar) { return baz; }).bind(this). This automatically captures the current value of “this” in scope, which is more often than not what you want. The proposal even states “dynamic this binding is an oft-fired footgun.”

http://jsnext.blogspot.com/2012/07/arrow-functions.html

>Arrow Functions are lexically bound to the 'this' of where it is declared. In other words, when an Arrow Function is declared, whatever the scope is at that time, that is 'this'. [...] Why add Arrow Functions? Why add this? We already understood what was going on... so why change it? I think that Brendan Eich has provided a great list of reasons ('Rationale' section): [...] However, we don’t want CoffeeScript’s ->, it’s confusing to have two arrows and dynamic this binding is an oft-fired footgun.

What exactly do you believe Brendan Eich meant by "dynamic this binding"? How can "this" be dynamically bound, yet behave "like an implicit parameter with lexical scope" (as you wrongly claim) at the same time?

Is Brendan Eich and everyone else in the JavaScript and TypeScript communities mistaken, and they foolishly added fat arrow functions to JavaScript for no reason, but nobody pointed out that embarrassing mistake until you came along?

If you're right, then you're barking up the wrong tree by arguing with me about it, so by all means, get on Twitter and tell Brendan Eich himself, ASAP! Your argument is with him and everyone else, not me. Maybe it's not too late to turn that ship around, but in my opinion it's already sailed.

But if you're wrong, then you probably have a lot of bugs to fix in your code, and should stay off Twitter.

If you truly believe in your heart of hearts that "this" is lexically scoped, you have definitely proven my and Brendan's point that "this" is a terrible "oft-fired footgun" that causes lots of deep confusion and insidious misunderstanding: just take a step back and look at how sure you are of yourself. Because "this" is certainly more mysterious and dangerous than YOU believe it is.

Re:Is there any code in Firefox (as of 2020) that comes from... by goto11 on Monday March 30, 2020 @03:10AM (#22725849)
Regular JavaScript functions work as if there is an implicit "this" parameter (which gets the value from the left-hand side of the call expression rather than the argument list). Fat-arrow function on the other hand does not change "this", which means the "this" binding inside a fat-arrow function is the one from the containing scope. But in both cases the scope of the "this" binding is lexical.

Dynamic scope means something different. Dynamic scope means that a variable binding from the call site is visible in a called function and down the call stack. This is not how "this" works. The "this" binding at the call site is never visible inside the called function, unless the called function happen to be nested inside the same lexical scope.

"this" is confusing because it gets rebound at every call, even if the function is not called using dot expression. But it is not because of dynamic scoping.