我正在学习ES6中的课程......
我想以某种形式使用私有属性,以便只能从类的实例调用某些方法。
例如使用符号...
/* A.js */
const _privateMethod = Symbol('_privateMethod')
class A {
[_privateMethod]() {
return 'yup'
}
do() {
return this[_privateMethod]()
}
}
const a = new A()
a.do() /* yup */
..._ privateMethod无法直接调用。到目前为止一切都很好。
但是,我想知道如何在继承自A的类中重写_privateMethod。例如,以下内容将不起作用:
/* B.js */
const _privateMethod = Symbol('_privateMethod')
class B extends A {
[_privateMethod]() {
return 'nope'
}
}
const b = new B()
b.do() /* yup */
如何建议这样做?
答案 0 :(得分:3)
再次调用Symbol('_privateMethod')
会创建一个新的不同符号(即使它具有相同的描述)。您正在使用不同的密钥创建不同的方法,而不是覆盖原始密钥。
您需要使用完全相同的相同符号来定义子类中的方法。您可以从Object.getOwnPropertySymbols(A.prototype)
获取它,也可以将_privatMethod
符号从A.js导出为常量并将其导入B.js(与class A
一起)。但是,如果你想使类可扩展,我建议根本不使用符号。
答案 1 :(得分:2)
编程概念在实践中使用的原因是它们为开发人员提供了一些好处,这也包括封装。如果它提供的缺点多于好处,这意味着它不应该被应用,或者它的应用方式是错误的。
JavaScript没有提供封装作为语言功能。符号是一种可以接受的实现方式,但它的特殊性使其不适合任务。
作为私人(受保护)成员的标识符的符号应始终与其所属的类一起导出:
export const _privateMethod = Symbol('_privateMethod');
export class A {
[_privateMethod]() {/*...*/}
/*...*/
}
...
import { _privateMethod, A } from './a';
class B extends A {
[_privateMethod]() {/*...*/}
}
如果这不可能或不实用,这意味着符号是封装的不恰当选择,因为它提供了缺点而没有任何实际好处。
由于信息隐藏不能在JavaScript中提供安全性(符号可以通过Object.getOwnPropertySymbols
访问),因此封装机制的替代方法是使用匈牙利符号和/或JSDoc注释。它们为开发人员提供有关公共接口的必要信息:
export class A {
/** @protected */
_privateMethod() {/*...*/}
/*...*/
}
答案 2 :(得分:0)
您可以使用Object.getOwnPropertySymbols()
功能:
const A = (function() {
const _privateMethod = Symbol('_privateMethod')
return class A {
[_privateMethod]() {
return 'yup'
}
do() {
return this[_privateMethod]()
}
}
}());
(function() {
const _privateMethod = Object.getOwnPropertySymbols(A.prototype)
.find(x => x.toString() === 'Symbol(_privateMethod)')
class B extends A {
[_privateMethod]() {
return 'nope'
}
}
const b = new B()
console.log(b.do());
}());
答案 3 :(得分:0)
你已经有了正确的答案,请查看
const _privateMethod = Symbol('_privateMethod')
class A {
[_privateMethod]() {
return 'yup'
}
do() {
return this[_privateMethod]()
}
}
const a = new A()
document.write(a.do()+ "<br><br>" )
class B extends A {
[_privateMethod]() {
return 'nope'
}
}
const b = new B()
document.write(b.do()+ "<br><br>")