Giter Site home page Giter Site logo

Comments (12)

jamiebuilds avatar jamiebuilds commented on July 30, 2024 5

Yeah, sorry I updated the code.

The way that I think to teach #x is to explain that it creates a special key only available to the class and gets used similar to a computed member.

Or in code form:

const Foo = (() => {
  let x = createPrivateKey();
  
  return class Foo {
    constructor(x) { this[x] = x; }
    print() { console.log(this[x]); }
  };
}());

// no access to `x`

With this.#x the behavior is fairly intuitive (ignoring how unintuitive this is on its own), teaching this way is reinforcing how it reads syntactically.

But the #x shorthand isn't intuitive in that way unless you know that this. is implied.

Based on the feedback from my post, people are already confused by:

class Foo {
  #x;
  method(foo /*: Foo */) {
    foo.#x
  }
}

Because they think #x is a variable that you're assigning to instead of a key that you have access to. I think that #x = 1; reinforces the (incorrect) idea that it is a variable assignment to #x instead of a key.

from proposal-class-fields.

ljharb avatar ljharb commented on July 30, 2024 1

Implicit shorthand creates confusion; I'd prefer static.x as a shorthand for Foo.x.

This would also be useful for static methods. Perhaps it should be part of a separate proposal, however?

from proposal-class-fields.

littledan avatar littledan commented on July 30, 2024 1

@thejameskyle (I assume you meant to write foo1.print.call(foo2).) Do you mean that the syntax implies the "lexically scoped value" intuition, and you'd expect 1 to be printed, even though it definitely prints 2?

from proposal-class-fields.

Ltrlg avatar Ltrlg commented on July 30, 2024

from proposal-class-fields.

littledan avatar littledan commented on July 30, 2024

Let's pursue this in a separate proposal; public properties are just based on normal property access, so the accesses are also not necessarily from declarations.

Personally, I don't see the problem with Foo.x. But closing because it'd be better to make a separate proposal.

from proposal-class-fields.

peey avatar peey commented on July 30, 2024

Do note that the reason behind my original suggestion (not static.x, but direct access using x and #x) was to give a different (and more well-known) meaning to the shorthand syntax, since its existence in the private fields proposal is being criticized.

Shorthand syntax proposed here needn't be confusing, since it's already used by at least one language that I know of. Perhaps it can be thought of as block-scoped variable declaration (the block being the body of the class)

from proposal-class-fields.

littledan avatar littledan commented on July 30, 2024

OK, sorry for reading it too quickly.

This would work the same for private fields (and existing shorthand will have to be dropped in favour of this).

What do you mean by this? Most of the time private field shorthand will be used, it would be referencing instances, not static.

If we didn't drop the original shorthand: this is a completely orthogonal, different kind of shorthand; it's not really much of a counterpart of the private fields shorthand, since you'd expect static.#x to work--it's along a different axis. An expectation that there be shorthand for everything sounds like an argument against private shorthand, not for it.

Shorthand syntax proposed here needn't be confusing, since it's already used by at least one language that I know of. Perhaps it can be thought of as block-scoped variable declaration (the block being the body of the class)

Actually, I think this "block scoped variable declaration" intuition is a little problematic. It makes it surprising that there is support for other.#x as well. I hope users can learn that #x is sugar for this.#x, and the latter is the more basic form, as @thejameskyle's article explains it. cc @ashleygwilliams @wycats

from proposal-class-fields.

jamiebuilds avatar jamiebuilds commented on July 30, 2024

I'm a bit concerned about the shorthand syntax when methods are called with a different context.

class Foo {
  #x;
  constructor(x) { #x = x; }
  print() { console.log(#x); }
}

let foo1 = new Foo(1);
let foo2 = new Foo(2);

foo1.print.call(foo2);

Going off the reading of the syntax alone it is ambiguous what this is going to log.

from proposal-class-fields.

peey avatar peey commented on July 30, 2024

This would work the same for private fields (and existing shorthand will have to be dropped in favour of this).

What do you mean by this?

My position on the shorthand syntax is that

  • There should be only one way to access private property of the current object, and that should be this.#property since
    • It matches with our expectations of #property belonging to this as happens with normal object properties, e.g. this.property
    • It is consistent with accessing private properties of other instances of same class in class methods like foo.#property
  • The shorthand syntax should be dropped from the proposal

But simultaneously, I also got an idea that would perhaps be better suited as a different proposal altogether as ljharb suggested. The idea uses the shorthand syntax for something else - unqualified access for static private properties.

Demonstrating with a detailed example,

var someVariable = 10;
class Bar {
   static publicProperty = 20;
   static #privateProperty = 30;
   #ownPrivateProperty = 40;

   foo () {
        #privateProperty++;
        publicProperty++;
   }

   getPrivateValue() {
       return #privateProperty;
   }
  
  baz() {
     someVariable++;
  }

  ban() {
     this.#ownPrivateProperty++;
  }
  
  getOwnPrivateValue() {
     return this.#ownPrivateProperty;
  }
  
  bat() {
     nonExistentIdentifier++;
  }
}

var o = new Bar();
o.foo();
assert.equal(Bar.publicProperty, 21);
assert.equal(o.getPrivateValue(), 31);

o.ban();
assert.equal(o.getOwnPrivateValue(), 41);

o.baz();
assert.equal(someVariable, 11);

o.bat(); // throws ReferenceError because it neither found a lexical binding nor a static property with the name nonExistingIdentifier 

Instead of the shorthand #property referring to this.#property it refers to the static private property of the class Bar

from proposal-class-fields.

littledan avatar littledan commented on July 30, 2024

@peey Are you saying that you expect that if the #foo shorthand exists to get static private fields within a static method, then you could use foo to refer to a public static field, by virtue of analogy?

(In your example, you meant to put static in front of getPrivateValue() {, right? Otherwise, you'd get an undefined-is-not-a-function TypeError before reaching the part you're calling unintutiive.)

from proposal-class-fields.

peey avatar peey commented on July 30, 2024

@littledan I have fixed the code example. I meant to use getPrivateValue as a regular method, not a static method, so I've fixed where I incorrectly used it as assert.equal(Bar.getPrivateValue(), 31) to assert.equal(o.getPrivateValue(), 31)

I'm proposing that

  • #foo shorthand should always refer to the static property #foo of a class, be it in a static method or a non-static method
  • if foo is a public static field for a class, then foo should refer to the static property foo of that class, be it in a static method or non-static method

from proposal-class-fields.

littledan avatar littledan commented on July 30, 2024

Let's take these two suggestions separately:

  • For #foo on a static member always "working", regardless of the receiver: This is basically to say that #foo acts like a lexically scoped variable, rather than a member of the constructor. This idea actually bares a lot of resemblance to an open question for private methods (which I still need to write up)--should private methods type-check their receiver, or "just work" since the value is always the same? I think we could decide either way, and if we go down the second path, it'd be reasonable to do something similar for private static fields.
  • For public static fields, it's a bit different. Because it's an ordinary public property, code outside the class can change it, or even define a getter/setter--what effect should that have? Should it be possible for two things to get out of sync? And you might imagine that whatever is done for public static properties works for public methods too--should we add that? Given the complexity and cross-cutting issues to make something consistent, I think the motivation for this shorthand would have to be explained a bit more fully to add this feature.

from proposal-class-fields.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.