I'm not sure why anyone who's familiar with how "this" works would expect behavior any different than what I explained ...
Let's disect this chunk of code:
class C {
f() {
const data = {
get f: () => this
}
}
}
First we have f()
. When f() gets called a "this" value gets implicitly passed in, most likely it'll be an instance of C. During the invocation of f()
there's no reason to expect that the value of "this" will suddently be anything different within any sub-expression. The only time it should change is if you're defining another function, which may also have "this" get implicitly passed in that shadows the outer this.
Next we have get f: <expression>
. That is within the body of f(), so it's this
should be bound to what was implicitly passed in to f() - no reason to expect anything different here.
Inside of this expression we're creating an arrow function. The arrow function captures the value of this
from its surrounding scope, so whenever the arrow function executes, the "this" value will be whatever it was when f()
was invoked.
Note that nothing in those above steps had anything to do with the fact that we were doing a get x
- we could have been doing any of the following things instead, and it would have worked exactly the same, because all of these arrow functions would have been executed in the context of f():
f() {
const data = {
a: () => this // "this" got captures from f()
}
const b = () => this // "this" got captures from f()
2 + (() => this)() // "this" got captured from f()
// etc
}
Having the value of "this" get shadowed in a particular sub-expression would be odd and unintuitive, and would go against what anyone would have expected, if they've reached the point of finally understanding the oddities of "this". I can't see any reason why someone might expect "this" to behave any differently inside "get x: () => this
" over "x: () => this
" - if so, would they also expect "this" to behave differently inside potential future language features, like, perhaps "readonly x: () => this
"?
Even if people don't really understand how "this" binding works, I would argues that there are many cases where an arrow function would provide a more intuitive result than a normal function. For example:
class User {
...
#name
getInfo() {
return {
get name() {
return this.#name // Error! this.#name does not exist
},
get name2 = () => this.#name // Works, as one could resonably expect
}
}
}
Umm... and I guess that example also showcases a useful functionality difference that this proposal provides - how else would you use the correct "this" binding in that example? By renaming the outer this to self?