I make it!

```js
"use strict";

// utility
function createProtectedStorage() {
  const wm = new WeakMap();

  return (self, protectedClass) => {
    const map = wm.get(self);

    if(protectedClass == null) {
      if(map) {
        return map;
      } else {
        const ret = Object.create(null);
        wm.set(self, ret);
        return ret;
      }
    }

    const p = new protectedClass(self);
    if(map) {
      for(let key of Object.getOwnPropertyNames(map)) {
        const descriptor = Object.getOwnPropertyDescriptor(map, key);
        Object.defineProperty(p, key, descriptor);
      }
    }
    wm.set(self, p);
    return p;
  }
}

const _ = createProtectedStorage();


class Protected_A {

  constructor(publicThis) {
    this.publicThis = publicThis;
  }

  getName() {
    return `${this.publicThis.name} ${this.lastName}`;
  }
}

class A {

  constructor(name, lastName) {
    // protected this
    if(new.target === A) {
      _(this, Protected_A);
    }

    // public property
    this.name = name;

    // protected property
    Object.defineProperty(_(this), "lastName", {
      enumerable: false,
      configurable: false,
      writable: false,
      value: lastName
    });
  }

  callGetName() {
    // call protected method
    return _(this).getName();
  }
}

// extends
class Protected_B extends Protected_A {

        constructor(publicThis) {
                super(publicThis);
        }

        getAge() {
                return this.age;
        }
        
}

class B extends A {

    constructor(name, lastName, age) {
        super(name, lastName);

        // protected this
        if(new.target === B)    _(this, Protected_B);

        // protected property
        _(this).age = age;
    }

    callGetAge() {
        return _(this).getAge();
    }

    // added
    getData() {
        return {
            name: _(this).getName(), // Protected_A
            age:  _(this).getAge()
        }
    }

    getLastNameDescriptor() {
      return Object.getOwnPropertyDescriptor(_(this), "lastName");
    }

    getAgeDescriptor() {
      return Object.getOwnPropertyDescriptor(_(this), "age");
    }

}

// test
const b = new B("foo", "bar", 18);

// "foo bar"
console.log(b.callGetName());

// 18
console.log(b.callGetAge());

// { "name": "foo bar", "age": 18 }
console.log(b.getData());

// { "value": "bar", "writable": false, "enumerable": false, "configurable": false }
console.log(b.getLastNameDescriptor());

// { "value": 18, "writable": true, "enumerable": true, "configurable": true }
console.log(b.getAgeDescriptor());
```
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to