3 ms·
> is NOT an object property But it is an object property, just like everything else attached to "this". That "this.foo" is not "this.#foo" that's because "foo
by bad_user 8y ago
> is NOT an object property
But it is an object property, just like everything else attached to "this".
That "this.foo" is not "this.#foo" that's because "foo" is a different key than "#foo".
- Ajedi32 8y agoIt's not merely a different key; it's a completely different _type_ of key. I'm not sure how it's implemented internally, but `this.#foo != this['#foo']`.
- bad_user 8y agoObjects in JavaScript are just maps, so technically speaking if they disallow "this[#foo]", it's just a cheap trick.
- Ajedi32 8y agoThey don't disallow `this["#foo"]`. It's a completely different thing than `this.#foo` though. Think of it like this: this["#foo"] = "Value A" this.#foo = "Value B" console.log(this["#foo"]) //=> "Value A" console.log(this.#foo) //=> "Value B" That's why people are saying that `this.#foo` is not an object property. You can think of it like one if you want, but it's not really the same thing.
- simias 8y agoI only write a tiny bit of JS (and I mostly hate it to be honest) but what's the reason for this difference? Why not make them object properties to make the language more regular? I know this is very non-constructive but reading through these threads and these proposed improvements to modern JS the expression "polishing a turd" pops up in my mind repeatedly. That people chose to bring this thing out of the browser to use as a general purpose language is rather baffling to me. I can't wait for WebAssembly to become more mainstream, then I'll be able to archive my little knowledge of JS deep into my brain, alongside Perl and TCL. </nonconstructive rant>
- Ajedi32 8y agoIf they were object properties, then they wouldn't really be private. You can't throw an error on `this["#foo"]` because then you'd be publicly exposing the fact that a private field `this.#foo` exists.
- nwienert 8y agoAbove _ryan_ posts that the main reason they implemented it like this was so people wouldn’t use them and cause library maintainers pain. But just “knowing they exist” is not causing any pain for a library developer, as long as they can’t read the value. So I don’t understand the need to also hide the fact they exist. What’s the use case there? It seems you get all the benefit with almost no downside by just making them non-read/write but by going fully to non-enumerable you not introduce two massive downsides: 1. Introducing a whole new syntax that has multiple irregularities (property access) and uses a special character. 2. Now can confusingly have the same public and private names on the same class.
- __ryan__ 8y ago1. Introducing a whole new syntax that has multiple irregularities (property access) and uses a special character. I sincerely fail to see how this has irregularities. It's straightforward. x.#prop is always a private field access and x.prop is always x["prop"] which is always an object property access. 2. Now can confusingly have the same public and private names on the same class. I know what you're saying, but the reason it is confusing is because it is incorrect. You cannot have have any same public and private names because private names must start with # and public names cannot start with #. Private field names exist only in a class-definition-bound namespace. I know you can't think of a use case. But the committee of TC39 (language maintainers, popular library creators and maintainers) have thought of the use cases and have clearly decided it is useful.
- abritinthebay 8y agoIf I had to guess it’ll be some kind of named Symbol under the hood.
- __ryan__ 8y agoNot accurate. The private fields described in the spec are not properties on the object's map. Thats why they need to differentiate intention at the call site. The current idea is that private fields are kinda like this: export class Bar { #foo = 100; setFoo(value) { this.#foo = value; } getFoo() { return this.#foo; } getFooFromOtherBar(otherBar) { return otherBar.#foo; } } // similar to (but implemented differently I'm sure) const barPrivate = new WeakMap(); // properties are only private if this is never exported export class BarWithoutPrivateFields { constructor() { barPrivate.set(this, {}); barPrivate.get(this).foo = 100; } setFoo(value) { barPrivate.get(this).foo = value; } getFoo() { return barPrivate.get(this).foo; } getFooFromOtherBar(otherBar) { return barPrivate.get(otherBar).foo; } } It is NOT a property key!