是否可以在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'必须在一个外围类中声明
其他回答
我现在听到的建议是使用WeakMaps来保存私人数据,以供其他看客参考。
下面是一个更清晰、有效的例子:
function storePrivateProperties(a, b, c, d) {
let privateData = new WeakMap;
// unique object as key, weak map can only accept object as key, when key is no longer referened, garbage collector claims the key-value
let keyA = {}, keyB = {}, keyC = {}, keyD = {};
privateData.set(keyA, a);
privateData.set(keyB, b);
privateData.set(keyC, c);
privateData.set(keyD, d);
return {
logPrivateKey(key) {
switch(key) {
case "a":
console.log(privateData.get(keyA));
break;
case "b":
console.log(privateData.get(keyB));
break;
case "c":
console.log(privateData.get(keyC));
break;
case "d":
console.log(privateData.set(keyD));
break;
default:
console.log(`There is no value for ${key}`)
}
}
}
}
class Something {
constructor(){
var _property = "test";
Object.defineProperty(this, "property", {
get: function(){ return _property}
});
}
}
var instance = new Something();
console.log(instance.property); //=> "test"
instance.property = "can read from outside, but can't write";
console.log(instance.property); //=> "test"
答案是“不”。但是你可以像这样创建对属性的私有访问:
使用模块。模块中的所有内容都是私有的,除非使用export关键字将其设为公有。 在模块内部,使用函数闭包:http://www.kirupa.com/html5/closures_in_javascript.htm
(可以使用符号来确保隐私的建议在ES6规范的早期版本中是正确的,但现在不再是这样:https://mail.mozilla.org/pipermail/es-discuss/2014-January/035604.html和https://stackoverflow.com/a/22280202/1282216。有关符号和隐私的详细讨论,请参阅:https://curiosity-driven.org/private-properties-in-javascript)
甚至Typescript也做不到。从他们的文档来看:
当成员被标记为private时,就不能从其包含类的外部访问它。例如: 动物类{ 私有名称:字符串; 构造函数(名称:字符串){this.name =名称;} } 新的动物(猫). name;//错误:'name'是private;
但在他们的操场上,这说明:
var Animal = (function () {
function Animal(theName) {
this.name = theName;
}
return Animal;
}());
console.log(new Animal("Cat").name);
所以他们的“私人”关键字是无效的。
我们可以使用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