Access Modifiers (Private, Protected) in ES6

别等时光非礼了梦想. 提交于 2019-11-30 04:00:43
Sheepy

Private properties

In ES6 (and before), all private property implementations rely on closure.

People have been doing it even before JavaScript has versions. WeakMap is just a variation that removes the need of new scope and new functions for each new object, at cost of access speed.

Symbol is a ES6 variation that hides the attribute from common operations, such as simple property access or for in.

var MyClass;
( () => {
  // Define a scoped symbol for private property A.
  const PropA = Symbol( 'A' );
  // Define the class once we have all symbols
  MyClass = class {
    someFunction () {
      return "I can read " + this[ PropA ]; // Access private property
    }
  }
  MyClass.prototype[ PropA ] = 'Private property or method';
})();

// function in the closure can access the private property.
var myObject = new MyClass();
alert( myObject.someFunction() );

// But we cannot "recreate" the Symbol externally.
alert( myObject[ Symbol( 'A' ) ] ); // undefined

// However if someone *really* must access it...
var symbols = Object.getOwnPropertySymbols( myObject.__proto__ );
alert( myObject[ symbols[ 0 ] ] );

As seen above, it can be worked around by Object.getOwnPropertySymbols(). Despite its existence, I always choice symbol over WeakMap. The code is cleaner, simpler, less gc work, and (I think) more efficient.

I personally avoid class, too. Object.create is much simpler. But that is out of scope.


Protected properties

Protected properties, by its nature, requires executing function to know the object of the calling code, to judge whether it should be granted access.

This is impossible in JS, not because ES6 has no real class, but because caller context is simply unavailable.

Due to various special natures of JavaScript, for the foreseeable future protected properties shall remain impossible.

Alternatively...


Package properties

Some languages have semi-protected properties, sometimes called "package private", where the method / property is accessible to members in the same module / package.

ES6 can implement it with closure. It is exactly the same as the private property code above - just share the scope and its symbols with multiple prototypes.

But this is impractical, since this requires that the whole module be defined under same closed scope, i.e. in a single file. But it is an option nonetheless.

I'm late to answer this, but it is possible to emulate private AND protected methods in javascript.

Private methods/properties

Uses the well known Symbol approach

const someMethod = Symbol()
const someProperty = Symbol()

export default class Parent {
  constructor () {
    this[someProperty] = 'and a private property'
  }

  [someMethod] () {
    console.log('this is a private method')
    console.log(this[someProperty])
  }

  callPrivateMethod () {
    this[someMethod]()
  }
}

Protected methods/properties

By their nature, protected members are visible to derived classes. They must also mimic the super.method pattern.

symbols.js

export default {
   protectedMethod: Symbol()
}

parent.js

import symbols from './symbols'

const someMethod = Symbol()
const someProperty = Symbol()

export default class Parent {
  constructor () {
    this[someProperty] = 'and a private property'
  }

  [someMethod] () {
    console.log('this is a private method')
    console.log(this[someProperty])
  }

  [symbols.protectedMethod] () {
    console.log('I am the parent')
  }

  callPrivateMethod () {
    this[someMethod]()
  }
}

child.js

import Parent from './parent'
import symbols from './symbols'

export default class Child {
  [symbols.protectedMethod] () {
    console.log('I am the child')
    super[symbols.protectedMethod]()
  }

  callProtectedMethod () {
    this[symbols.protectedMethod]()
  }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!