是否可以在ES6类中创建私有属性?
举个例子。 如何阻止访问instance.property?
class Something {
constructor(){
this.property = "test";
}
}
var instance = new Something();
console.log(instance.property); //=> "test"
是否可以在ES6类中创建私有属性?
举个例子。 如何阻止访问instance.property?
class Something {
constructor(){
this.property = "test";
}
}
var instance = new Something();
console.log(instance.property); //=> "test"
当前回答
根据ES2022,我们可以在JavaScript类中添加私有属性和方法。
我们可以通过在私有字段的名称前预先挂起#来定义它们。
演示:
类Something { #property = "test";//通过在属性名后面加上#,我们使它成为私有的。 } var instance = new Something(); console.log(实例。#产权);私有字段'#property'必须在一个外围类中声明
其他回答
我们可以使用getter和setter来模拟类的私有属性。
eg 1
class FootballClub {
constructor (cname, cstadium, ccurrentmanager) {
this.name = cname;
this._stadium = cstadium; // we will treat this prop as private and give getter and setter for this.
this.currmanager = ccurrentmanager;
}
get stadium( ) {
return this._stadium.toUpperCase();
}
}
let club = new FootballClub("Arsenal", "Emirates" , "Arteta")
console.log(club);
//FootballClub {
// name: 'Arsenal',
// _stadium: 'Emirates',
// currmanager: 'Arteta'
// }
console.log( club.stadium ); // EMIRATES
club.stadium = "Highbury"; // TypeError: Cannot set property stadium of #<FootballClub> which has only a getter
在上面的例子中,我们没有给出stadium的setter方法,因此我们不能为它设置一个新值。在接下来的例子中,为体育场添加了一个setter
eg 2
class FootballClub {
constructor (cname, cstadium, ccurrentmanager) {
this.name = cname;
this._stadium = cstadium; // we will treat this prop as private and give getter and setter for this.
this.currmanager = ccurrentmanager;
}
get stadium( ) {
return this._stadium.toUpperCase();
}
set stadium(val) {
this._stadium = val;
}
}
let club = new FootballClub("Arsenal", "Emirates" , "Arteta")
console.log(club.stadium); // EMIRATES
club.stadium = "Emirates Stadium";
console.log(club.stadium); // EMIRATES STADIUM
我有一个解决办法,它很简单…虽然性能不是问题…但它确实有效,而且效果很好。
诀窍在于,在私有属性和函数被建立和标准化/采用之前,需要另一种解决方案,这是另一种解决方案…
class ClassPrivateProperties {
constructor(instance) {
const $this = instance;
let properties = {};
this.prop = (key, value = undefined) => {
if (!value) {
return properties[key];
} else {
properties[key] = value;
}
};
this.clear = instance => {
if ($this === instance) {
properties = {};
return true;
} else {
return false;
}
}
}
}
这是一个示例用法,可以是什么(如果你使用上面的感觉自由,使它更好)
class Test {
constructor() {
this._privateProps = new ClassPrivateProperties(this);
}
property(key, value = undefined) {
if (!value) {
return this._privateProps.prop(key);
} else {
this._privateProps.prop(key, value);
}
}
clear() { return this._privateProps.clear(this); }
}
const test = new test;
test.property('myKey','some value here');
console.log(test.property('myKey'));
就像我提到的,这个问题不是最好的,但它工作,使属性真正的私有。
你可以试试这个https://www.npmjs.com/package/private-members
这个包将按实例保存成员。
const pvt = require('private-members');
const _ = pvt();
let Exemplo = (function () {
function Exemplo() {
_(this).msg = "Minha Mensagem";
}
_().mensagem = function() {
return _(this).msg;
}
Exemplo.prototype.showMsg = function () {
let msg = _(this).mensagem();
console.log(msg);
};
return Exemplo;
})();
module.exports = Exemplo;
现在大多数浏览器都支持私有类特性。
class Something {
#property;
constructor(){
this.#property = "test";
}
#privateMethod() {
return 'hello world';
}
getPrivateMessage() {
return this.#property;
}
}
const instance = new Something();
console.log(instance.property); //=> undefined
console.log(instance.privateMethod); //=> undefined
console.log(instance.getPrivateMessage()); //=> test
console.log(instance.#property); //=> Syntax error
使用ES6模块(最初由@d13提出)对我来说效果很好。它不能完美地模拟私有属性,但至少您可以确信,应该是私有的属性不会泄漏到类之外。这里有一个例子:
something.js
let _message = null;
const _greet = name => {
console.log('Hello ' + name);
};
export default class Something {
constructor(message) {
_message = message;
}
say() {
console.log(_message);
_greet('Bob');
}
};
然后消费代码可以是这样的:
import Something from './something.js';
const something = new Something('Sunny day!');
something.say();
something._message; // undefined
something._greet(); // exception
更新(重要):
正如@DanyalAytekin在评论中概述的那样,这些私有属性是静态的,因此在全球范围内。它们在处理单例对象时工作得很好,但在处理瞬态对象时必须小心。扩展上面的例子:
import Something from './something.js';
import Something2 from './something.js';
const a = new Something('a');
a.say(); // a
const b = new Something('b');
b.say(); // b
const c = new Something2('c');
c.say(); // c
a.say(); // c
b.say(); // c
c.say(); // c