{"action":"created","issue":{"url":"https://api.github.com/repos/jeffmo/es-class-static-properties-and-fields/issues/2","labels_url":"https://api.github.com/repos/jeffmo/es-class-static-properties-and-fields/issues/2/labels{/name}","comments_url":"https://api.github.com/repos/jeffmo/es-class-static-properties-and-fields/issues/2/comments","events_url":"https://api.github.com/repos/jeffmo/es-class-static-properties-and-fields/issues/2/events","html_url":"https://github.com/jeffmo/es-class-static-properties-and-fields/issues/2","id":107043248,"number":2,"title":"instance property declarations need to be in constructor scope","user":{"login":"erights","id":273868,"avatar_url":"https://avatars.githubusercontent.com/u/273868?v=3","gravatar_id":"","url":"https://api.github.com/users/erights","html_url":"https://github.com/erights","followers_url":"https://api.github.com/users/erights/followers","following_url":"https://api.github.com/users/erights/following{/other_user}","gists_url":"https://api.github.com/users/erights/gists{/gist_id}","starred_url":"https://api.github.com/users/erights/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/erights/subscriptions","organizations_url":"https://api.github.com/users/erights/orgs","repos_url":"https://api.github.com/users/erights/repos","events_url":"https://api.github.com/users/erights/events{/privacy}","received_events_url":"https://api.github.com/users/erights/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":18,"created_at":"2015-09-17T18:23:54Z","updated_at":"2015-09-29T06:24:55Z","closed_at":null,"body":"The proposal as of 9/17 places both [instance property declarations](https://github.com/jeffmo/es-class-properties#proposal-12-class-instance-properties) and [static property declarations](https://github.com/jeffmo/es-class-properties#proposal-22-class-static-properties) inside the class body. For static properties, this is exactly right, as static properties are per-class and are initialized once when the class is initialized. \r\n\r\nFor instance properties, putting the declaration in the class body is exactly wrong, because instance properties are per-instance precisely in order to vary from one instance to another. The expression used to initialize an instance need to be in the scope of the constructor, as the initial value will often be calculated based on constructor parameters.\r\n\r\nThe most common response to this objection is that the constructor can re-initialize these properties by assignment. But this confuses initialization with mutation. A declarative property declaration syntax needs to be able to grow into the ability to declare const properties, i.e., non-writable, non-configurable data properties. Whether the ability to declare const properties is provided by syntax or by declaration, their unassignable nature prevents this re-initialization in the constructor.\r\n\r\nTo make this repair to the proposal, we of course need an alternate concrete syntax proposal. Here are some choices:\r\n\r\n\r\n## Overload the variable declaration syntax\r\n\r\nThe common ES6 way to give an instance properties is by assignment in the constructor body, such as:\r\n\r\n```javascript\r\nclass Point {\r\n    constructor(x, y) {\r\n        this.x = x;\r\n        this.y = y;\r\n    }\r\n}\r\n```\r\n\r\nThe first proposal would simply turn these assignments into declarative property initializations by prefixing them with `let` or `const`:\r\n\r\n```javascript\r\nclass Point {\r\n    constructor(x, y) {\r\n        const this.x = x;\r\n        const this.y = y;\r\n    }\r\n}\r\n```\r\n\r\nThis syntax is unambiguous, as it is currently illegal under the ES6 grammar.\r\n\r\nUsing the `const` keyword declares the property to be a non-writable, non-configurable data property. Using the `let` keyword makes a writable, non-configurable data property. Conceivably, using the `var` keyword would make a writable configurable data property, although there's not much point since assignment already does this. In all cases, these declarations could be decorated.\r\n\r\nIn a base class as above, perhaps all these declarations must come textually before the first non-declaration use of `this`, in order to prevent the instance from being observed before it is initialized. In a derived class constructor, perhaps all these declarations must come before the `super` call, while `this` is in a temporal dead zone, for the same reason. However, either of these requirements impedes refactoring ES6 code to turn instance assignment into initialization.\r\n\r\n\r\n## Use the reserved \"public\" keyword\r\n\r\nThis proposal is like the previous one, but using (and using up) the reserved \"public\" keyword rather than overloading the meaning of `let` and `const`:\r\n\r\n```javascript\r\nclass Point {\r\n    constructor(x, y) {\r\n        public this.x = x;\r\n        public this.y = y;\r\n    }\r\n}\r\n```\r\n\r\nor perhaps\r\n\r\n```javascript\r\nclass Point {\r\n    constructor(x, y) {\r\n        public x = x;\r\n        public y = y;\r\n    }\r\n}\r\n```\r\n\r\nBy default, this makes writable non-configurable data properties. To declare a non-writable property instead, you'd use a decorator.\r\n\r\nSince `public`, unlike `let` and `const`, is not already associated with a TDZ concept, the initialization-time considerations above do not have as much force. Nevertheless, observing an uninitialized instance is a hazard that these restrictions can help programmers avoid.\r\n\r\nAnother possible advantage of `public` is that private fields might then be declared with the same syntax but using the keyword `private`.\r\n\r\n\r\n## Use C++-like property initialization syntax\r\n\r\n```javascript\r\nclass Point {\r\n    constructor(x, y)\r\n      :x(x), y(y) {\r\n    }\r\n}\r\n```\r\n\r\nPersonally I find it ugly. With decorators, they'd be even uglier. I list it because, given precedent, it should at least be mentioned as a candidate."},"comment":{"url":"https://api.github.com/repos/jeffmo/es-class-static-properties-and-fields/issues/comments/143957686","html_url":"https://github.com/jeffmo/es-class-static-properties-and-fields/issues/2#issuecomment-143957686","issue_url":"https://api.github.com/repos/jeffmo/es-class-static-properties-and-fields/issues/2","id":143957686,"user":{"login":"jeffmo","id":498293,"avatar_url":"https://avatars.githubusercontent.com/u/498293?v=3","gravatar_id":"","url":"https://api.github.com/users/jeffmo","html_url":"https://github.com/jeffmo","followers_url":"https://api.github.com/users/jeffmo/followers","following_url":"https://api.github.com/users/jeffmo/following{/other_user}","gists_url":"https://api.github.com/users/jeffmo/gists{/gist_id}","starred_url":"https://api.github.com/users/jeffmo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jeffmo/subscriptions","organizations_url":"https://api.github.com/users/jeffmo/orgs","repos_url":"https://api.github.com/users/jeffmo/repos","events_url":"https://api.github.com/users/jeffmo/events{/privacy}","received_events_url":"https://api.github.com/users/jeffmo/received_events","type":"User","site_admin":false},"created_at":"2015-09-29T06:24:55Z","updated_at":"2015-09-29T06:24:55Z","body":"@erights: Avoiding boilerplate is not the only purpose of this proposal but when it's possible to avoid, doing so is of significant appeal.\r\n\r\nCurrently there are 2 framework authors involved with this proposal (React and Ember) who can each cite prevalent patterns for their respective frameworks whereby non-constructor-dependent initialization will be common. [The proposal shows one such example using React.](https://github.com/jeffmo/es-class-properties/blob/master/README.md#expressiveness--boilerplate) I'm quite sure there are many other cases that will benefit equally as well such as auto-uuid initializers; And it is trivial to extrapolate the auto-uuid example into all sorts of less generic situations (csrf-token acquisition, registration of the instance while retaining a ref to the key in the registry, etc, etc).\r\n\r\nGoing back to the originally expressed concern, though:\r\n\r\n> A declarative property declaration syntax needs to be able to grow into the ability to declare const properties, i.e., non-writable, non-configurable data properties\r\n\r\nGiven the decorator [described above](https://github.com/jeffmo/es-class-properties/issues/2#issuecomment-141455960), it seems clear that we can address the practicalities of single-initialization in userland in the interim at least. Moreover if we wish to include language level support for const properties at some point, a future proposal could ensure this by marking const fields non-configurable at the time the constructor evaluation is complete (thereby allowing configurability only during initialization and/or construction time). The current proposal also still offers the option of expansion to private properties by way of a similar syntax (a special `#`-prefix syntax perhaps, or maybe a `private` keyword). @wycats has shown how this can work in his [big picture](https://github.com/wycats/javascript-decorators/blob/big-picture/README.md) discussion.\r\n\r\nAfter thinking this alternative through, however, it's become clear that there are some serious issues with it that just don't make sense. Namely the way that it places declarative descriptions about the class's prescriptive structure into an imperative statement-list position that executes at instantiation time. This introduces several bits of fall-out:\r\n\r\nWhen do field declaration decorators run? (these need to run at class definition time) Where can field declarations be positioned with respect to `super()` inside the constructor? If they sit above `super()`, they cannot refer to `this` (`this` isn't allocated yet). Do we require that field definitions happen immediately after the `super()` call? What happens if the pre-initialization logic returns early (i.e. before the `super()`)? In that case, did the field declarations count? It's a bit odd because they were added to the declarative definition of the class (observable via decorators + introspection), but yet they seem to be described conditionally? What happens if `super()` is itself called conditionally? What happens when a return or abrupt completion occurs in between or before field declaration statements come to execute?\r\n\r\nThe model here just doesn't make sense.\r\n\r\nUltimately we need a way to describe the fields on a class in terms of specified declarations that can be reflected and relied upon at instantiation time. Sometimes we wish to initialize those declarations with constructor-dependent data and other times not. The proposal as-is addresses both situations and does so in a familiar form that adds little complexity to the grammar and reduces boilerplate for a subset of use cases. I still find this to be the most compelling."}}