是否可以在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"
当前回答
正如我们所知,ES6类不支持私有属性。
下面是我使用的方法(可能会有帮助)。基本上,我是在工厂内部包装一个类。
function Animal(name) {
const privateData = 'NO experiments on animals have been done!';
class Animal {
constructor(_name) {
this.name = _name;
}
getName() {
return this.name
}
getDisclamer() {
return `${privateData} Including ${this.name}`
}
}
return new Animal(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
我现在听到的建议是使用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}`)
}
}
}
}
我相信在构造函数中使用闭包是可能获得“两全其美”的。有两种变化:
所有数据成员都是私有的
函数myFunc() { console.log(' x的值:' + this.x); this.myPrivateFunc (); } 函数myPrivateFunc() { console.log(' x的增强值:' +(此。X + 1)); } 类测试{ 构造函数(){ Let internal = { X: 2, }; 内部的。myPrivateFunc = myPrivateFunc.bind(内部); 这一点。myFunc = myFunc.bind(内部); } };
有些成员是私有的
注意:这确实很难看。如果您知道更好的解决方案,请编辑此回复。
function myFunc(priv, pub) { pub.y = 3; // The Test object now gets a member 'y' with value 3. console.log('Value of x: ' + priv.x); this.myPrivateFunc(); } function myPrivateFunc() { pub.z = 5; // The Test object now gets a member 'z' with value 3. console.log('Enhanced value of x: ' + (priv.x + 1)); } class Test { constructor() { let self = this; let internal = { x : 2, }; internal.myPrivateFunc = myPrivateFunc.bind(null, internal, self); this.myFunc = myFunc.bind(null, internal, self); } };
答案是“不”。但是你可以像这样创建对属性的私有访问:
使用模块。模块中的所有内容都是私有的,除非使用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)
大多数答案要么说不可能,要么要求你使用WeakMap或Symbol,这是ES6的特性,可能需要腻子。然而,还有另一种方法!看看这个:
// 1. Create closure var SomeClass = function() { // 2. Create `key` inside a closure var key = {}; // Function to create private storage var private = function() { var obj = {}; // return Function to access private storage using `key` return function(testkey) { if(key === testkey) return obj; // If `key` is wrong, then storage cannot be accessed console.error('Cannot access private properties'); return undefined; }; }; var SomeClass = function() { // 3. Create private storage this._ = private(); // 4. Access private storage using the `key` this._(key).priv_prop = 200; }; SomeClass.prototype.test = function() { console.log(this._(key).priv_prop); // Using property from prototype }; return SomeClass; }(); // Can access private property from within prototype var instance = new SomeClass(); instance.test(); // `200` logged // Cannot access private property from outside of the closure var wrong_key = {}; instance._(wrong_key); // undefined; error logged
我称这个方法为accessor pattern。基本思想是我们有一个闭包,闭包中有一个键,我们创建一个私有对象(在构造函数中),只有当你拥有键时才能访问它。
如果你感兴趣,你可以在我的文章中阅读更多有关这方面的内容。使用此方法,可以为每个对象创建不能在闭包外部访问的属性。因此,你可以在构造函数或原型中使用它们,但不能在其他任何地方使用。我还没有在任何地方见过这种方法,但我认为它真的很强大。