DEV Community

Discussion on: No, TypeScript is not OOP version of JavaScript

Collapse
 
cherif_b profile image
Cherif Bouchelaghem

Sure is doable like you said, but I have couple of concerns about your example:

What about when private is not initialized with hello value but needs to object have to be constructed using external data ?

What about performance when you have thousands of objects to create with closure?

I will be more than happy to read what is the correct meaning of encapsulation and how to do it?

I already do encapsulation (and private members) with classes(or prototypal inheritance if you will) inside modules with the help of the WeakMap

var state = new WeakMap();

/**
 * @class 
 */
class Todo {
    constructor(){
        state.set(this, {});
    }

    get name() {
        return state.get(this).name;
    }

    set name(name) {
        if (typeof name !== 'string') {
            throw('Todo name must be of string type');
        }

        state.get(this).name = name;
    }

    get description() {
        return state.get(this).description;
    }

    set description(description) {
        if (typeof description !== 'string') {
            throw('Todo description must be of string type');
        }
        state.get(this).description = description;
    }

    get status() {
        return state.get(this).status;
    }

    set status(status) {
        state.get(this).status = status;
    }

    markAsDone() {
        if (this.status === TodoStatus.DONE) {
            throw new Error('Todo is already done');
        }
        this.status = TodoStatus.DONE
    }

    reopen() {
        if (this.status === TodoStatus.OPEN) {
            throw new Error('Todo is already open');
        }
        this.status = TodoStatus.OPEN;
    }
}


module.exports = ({name, description}) => {
    const todo = new Todo();

    todo.name = name;
    todo.description = description;
    todo.status = TodoStatus.OPEN;

    return Object.freeze(todo);
};
Thread Thread
 
patroza profile image
Patrick Roza • Edited

I don't understand why you would do this.
If you want to break a program, you can break it one way or another, so why try to chase the perfect level of encapsulation? Most languages who support encapsulation better than JS, still allow access through reflection. It's an endless cat and mouse game. To what end?

In the end, it's important that your code communicates how it should be used,
that the right way is most convenient and well surfaced, and the wrong way is harder.
private works just fine to achieve exactly that and other modifiers like readonly etc.

The only imo minor inconvenience of private compared to # is collision. Python solves that by prefixing the variable name with _ClassName_, transparently for you. You can do the same manually. Again it communicates that this variable should be considered as private state to the said class.

Sure # just makes it more convenient, so that's nice, but definitely not a requirement to me.
Nice hack to use WeakMap, but to me it's a waste of effort, increased maintenance hurdle/cost, cognitive load, and maybe even performance. Each much more important than achieving the perfect level of encapsulation imo.

Thread Thread
 
cherif_b profile image
Cherif Bouchelaghem • Edited

Patrick Roza, thank your for the replay, in my example I'm talking in the context of the current JS implementation not the next JS or TS, for sure typescript solved the issue for now with private properties/methods.

I use encapsulation mainly to avoid shared mutating state issue and avoid an example like the following:

delete obj.someProp;

I can freeze or use Object.defineProperty to achieve it, the later is more waste of effort.

I don't think that using WeakMaps has a big performance impact compared to closures.

Thread Thread
 
patroza profile image
Patrick Roza • Edited

I see, in TS trying to delete obj.someProp where someProp is marked readonly will be prevented by compiler.

yea I just noticed that in vanilla JS you are kind of left to the harder options like closures or Weakmap.
At the same time, JSDoc may be helpful too, as said communication is the most important part imo, achievable by:

  • naming: e.g _myprivate, _MyClass_myprivate etc
  • documentation: e.g /** @private */
  • tooling support for said options (lint/doc/editor)

Editor support is of course very helpful, and in that, I think TypeScript as a supported standard is perhaps very helpful.

Thread Thread
 
cherif_b profile image
Cherif Bouchelaghem

I agree, I use the example above for domain modeling with JS on nodejs, not in every part of my applications.

As you said, communication is important so I started switching to typescript.

+1 for the JSDoc.