Closed dhilt closed 4 years ago
Yes, it’s allowed; any value is allowed in a class property.
why would you want that though? wouldn't that create a new function for every instance of your class, as well as break prototype inheritance?
(also weird how arrow functions that normally don't have their own this
deviate from that behavior in this case, even though that's like almost their entire point)
wouldn't that create a new function for every instance of your class
Not always:
function fn() {}
class A { x = fn };
Also, it's consistent with how this code creates a new object for every instance of the class:
class A { x = {} }
as well as break prototype inheritance?
Yes, it would be similar (modulo the defineProperty
thing) to
class A {
constructor() {
this.fn = function () {};
}
}
If you want it to respect the normal prototype chain you can use an "old-style" method. Also, having a runtime error when a value is a function is super inconsistent with the rest of the language.
also weird how arrow functions that normally don't have their own this deviate from that behavior in this case, even though that's like almost their entire point
Arrow functions in class fields behave like normal arrow functions: they get this
from the outer scope.
class A {
x = this;
y = () => this;
}
let { x, y } = new A;
x === y();
guess i shouldn't have phrased that as a question.
Thanks for answering these questions, @ljharb and @nicolo-ribaudo .
my question wasn't answered, actually:
why would you want that though?
The biggest usecase is to use arrow functions. Normal methods are like normal functions, thus don't capture this
.
If you are looking for an example without arrow functions, here it is:
class ClickLogger {
el;
listener = function () { console.log("click!"); }
constructor(el) {
this.el = el;
}
attach() { this.el.addEventListener("click", this.listener) }
detach() { this.el.removeEventListener("click", this.listener) }
}
const logger1 = new ClickLogger(document.body);
const logger2 = new ClickLogger(document.body);
logger1.attach();
logger2.attach();
// Click on the document. It will log "click!" twice, because you have two loggers
logger2.detach();
// Click on the document. It will log "click!" once, because you still have one logger
If you use a normal class method, it won't attach the second logger and after you detach the first one it won't log anything, even if there is still the first logger.
That said, functions are normal value in JavaScript, and disallowing some specific values would be inconsistent with the rest of the language. I cannot think of a valid use case to allow passing the exact "JavaScript is a horrible language!!! 2732"
string as a parameter to an arrow function, but it doesn't mean that we should forbid it because, exactly like functions, it's a normal JavaScript value :shrug:.
Also, note that this proposal doesn't force you to use functions in class fields. If for your use case it's better to use a normal class method, you should still use it.
i never said anything about disallowing functions in 'fields'.
my point is any situation where a function 'field' can replace a prototype method is either an improper use of fields (after) or a weird use of methods (before).
you also mentioned inconsistency with the rest of the language multiple times, which is funny because it perfectly describes the entire idea of statements with delayed execution outside of functions (ie. this proposal).
my point is any situation where a function 'field' can replace a prototype method is either an improper use of fields (after) or a weird use of methods (before).
IMO, the opinion of @a-ejs is true regardless of whether the field is public or private. No doubt, this is an unpopular position.
I share that opinion - functions shouldn’t go in class fields/own data properties, except for bound prototype methods.
However, it wouldn’t be consistent or appropriate for the language to enforce an arbitrary distinction between values, especially when it wouldn’t be enforceable in non-field data properties.
While I'm no longer arguing for a change (since I recognize it to be futile), I must note that it is the design of this proposal that precludes such a reasonable restriction, not the language itself. However, I also understand that this is itself based on a fundamental difference between our (mine vs the TC39 consensus) understandings of the nature of a class.
There are tons of articles/docs mentioning Stage 3 Proposal in context of using Arrow functions as Class properties. Like, now we can use
instead of
I'm just trying to get a confirmation if it's something legal from the Stage 3 Proposal perspective. I've walked through all Stage 3 related repos and seems this one is the most appropriate. And here we see only Primitive as a Class property example in the Readme:
Does the Stage 3 Proposal really allow to use functions in that capacity or it's a kind of React/Babel/etc fantasy? If yes, it does, then maybe it would be a good idea to add a few words or even an example in the description?