ES6中的访问修饰符(专用,受保护)

Ala*_*kat 8 access-modifiers ecmascript-6

注意:我已经阅读了有关Symbols,WeekMaps和Maps 的以下SO问题和7个答案(截至目前),请在投票前阅读完整的问题:JavaScript ES6类中的私有属性
文章:https://esdiscuss.org/ 话题/ ES7-财产初始化

以下是我的Simple Class包含私有,公共和受保护的属性和方法.

  'use strict';
  class MyClass {
    constructor () {
      this.publicVar = 'This is Public Variable';
      this.privateVar = 'This is Private Variable';
      this.protectedVar = 'This is Protected Variable';
    } // Public Constructor Method.
    
    publicMethod () {
      console.log('   Accessing this.publicVar: ', this.publicVar);
      console.log('   Accessing this.privateVar: ', this.privateVar);
      console.log('   Accessing this.protectedVar: ', this.protectedVar);
      return 'Its Public Method'
    } // Public Method.

    privateMethod () {return 'Its Private Method'} // Private Method.
    protectedMethod () {return 'Its Protected Method'} // Protected Method.

    foo () {
      this.publicMethod();
      this.privateMethod();
      this.protectedMethod();
    } // Public Method
  } // end class
Run Code Online (Sandbox Code Playgroud)

我正在实例化Object并调用正在按预期工作的公共方法.

let MyObject = new MyClass;
MyObject.foo(); // Works fine.
console.log( MyObject.publicVar ); // Works
console.log( MyObject.publicMethod() ); // Works
Run Code Online (Sandbox Code Playgroud)

按预期工作.

现在我的问题.我知道在ES6规范中很少有像Symbol这样的东西,获得保护的当前解决方法是什么,私有变量/方法在ES6类上工作.

console.log( MyObject.privateVar ); // Works
console.log( MyObject.privateMethod() ); // Works
Run Code Online (Sandbox Code Playgroud)

我希望这个属性和方法只在它自己的类中可见.

console.log( MyObject.protectedVar ); // Works
console.log( MyObject.protectedMethod() ); // Works
Run Code Online (Sandbox Code Playgroud)

我希望这个属性和方法在它自己的类和扩展它的类中可见.

需要解决方法/更好的解决方案以实现此行为

She*_*epy 10

私人财产

在ES6(以及之前)中,所有私有属性实现都依赖于闭包.

人们在JavaScript版本之前就已经这样做了.WeakMap只是一种变体,它以访问速度为代价消除了对每个新对象的新范围和新功能的需求.

符号是一种ES6变体,它隐藏了常见操作的属性,例如简单的属性访问或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 ] ] );
Run Code Online (Sandbox Code Playgroud)

如上所示,它可以通过Object.getOwnPropertySymbols()来解决.尽管存在,我总是在WeakMap上选择符号.代码更清晰,更简单,更少gc工作,并且(我认为)更高效.

我个人也避免class. Object.create更简单.但这超出了范围.


受保护的属性

受保护的属性本质上需要执行函数来知道调用代码的对象,以判断是否应授予其访问权限.

这JS是不可能的,而不是因为ES6有没有真正的类,但由于呼叫者方面不具备的.

由于JavaScript的各种 特殊 性质,在可预见的未来,受保护的属性仍然是不可能的.

另外...


包属性

某些语言具有半保护属性,有时称为"包私有",其中方法/属性可供同一模块/包中的成员访问.

ES6可以通过关闭来实现它.它与上面的私有属性代码完全相同 - 只需与多个原型共享范围及其符号.

但这是不切实际的,因为这要求整个模块在相同的封闭范围内定义,即在单个文件中.但它仍然是一种选择.


Twi*_*fty 7

我迟到了回答这个问题,但可以在 javascript 中模拟私有和受保护的方法。

私有方法/属性

使用众所周知的符号方法

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]()
  }
}
Run Code Online (Sandbox Code Playgroud)

受保护的方法/属性

就其本质而言,受保护的成员对于派生类是可见的。他们还必须模仿这种super.method模式。

符号.js

export default {
   protectedMethod: Symbol()
}
Run Code Online (Sandbox Code Playgroud)

父.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]()
  }
}
Run Code Online (Sandbox Code Playgroud)

孩子.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]()
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是不受保护的,这是公开的,因为每个人都可以访问“符号”,或者我错过了什么? (3认同)
  • @BenjaminVanRyseghem,正是我的观点。如果您的代码打算写入受保护/私有字段,那么您必须导入符号。假设您发布了一个模块“string”,其中包含一个名为“_sum”的预期私有字段,任何用户都可以扩展或向该模块添加一个名为“_sum”的冲突字段。他们必须调查源头才能找到错误。使用符号可以防止这种情况发生。私有/受保护成员受到保护,防止意外写入。这并不是为了向用户隐藏字段,它只不过是一个安全网。任何语言都无法隐藏这些成员。 (2认同)