是否可以在ES6类中创建私有属性?

举个例子。 如何阻止访问instance.property?

class Something {
  constructor(){
    this.property = "test";
  }
}

var instance = new Something();
console.log(instance.property); //=> "test"

当前回答

我相信在构造函数中使用闭包是可能获得“两全其美”的。有两种变化:

所有数据成员都是私有的

函数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); } };

其他回答

在JS中获得真正隐私的唯一方法是通过作用域,因此不可能有一个属性是this的成员,只能在组件内部访问。在ES6中存储真正私有数据的最佳方法是使用WeakMap。

const privateProp1 = new WeakMap();
const privateProp2 = new WeakMap();

class SomeClass {
  constructor() {
    privateProp1.set(this, "I am Private1");
    privateProp2.set(this, "I am Private2");

    this.publicVar = "I am public";
    this.publicMethod = () => {
      console.log(privateProp1.get(this), privateProp2.get(this))
    };        
  }

  printPrivate() {
    console.log(privateProp1.get(this));
  }
}

显然,这可能是一个缓慢的,肯定是丑陋的,但它确实提供了隐私。

请记住,即使这样也不是完美的,因为Javascript是动态的。有人仍然可以这样做

var oldSet = WeakMap.prototype.set;
WeakMap.prototype.set = function(key, value){
    // Store 'this', 'key', and 'value'
    return oldSet.call(this, key, value);
};

为了在值被存储时捕获它们,所以如果你想格外小心的话,你需要捕获一个对.set和.get的本地引用来显式使用,而不是依赖于可覆盖的原型。

const {set: WMSet, get: WMGet} = WeakMap.prototype;

const privateProp1 = new WeakMap();
const privateProp2 = new WeakMap();

class SomeClass {
  constructor() {
    WMSet.call(privateProp1, this, "I am Private1");
    WMSet.call(privateProp2, this, "I am Private2");

    this.publicVar = "I am public";
    this.publicMethod = () => {
      console.log(WMGet.call(privateProp1, this), WMGet.call(privateProp2, this))
    };        
  }

  printPrivate() {
    console.log(WMGet.call(privateProp1, this));
  }
}

这里,myThing变量是私有的,是闭包的一部分:

class Person {
  constructor() {

    var myThing = "Hello World";

    return {
      thing: myThing,
      sayThing: this.sayThing
    }
  }

  sayThing() {
    console.log(this.thing);
  }
}

var person = new Person();

console.log(person);

我认为Benjamin的答案在大多数情况下可能是最好的,直到语言本身支持显式私有变量。

但是,如果出于某种原因需要阻止使用object . getownpropertysymbols()进行访问,我考虑使用的一种方法是附加一个惟一的、不可配置的、不可枚举的、不可写的属性,可以将其用作构造中的每个对象的属性标识符(例如惟一的Symbol,如果您还没有其他一些惟一的属性,如id)。然后使用该标识符保存每个对象的“私有”变量的映射。

const privateVars = {};

class Something {
    constructor(){
        Object.defineProperty(this, '_sym', {
            configurable: false,
            enumerable: false,
            writable: false,
            value: Symbol()
        });

        var myPrivateVars = {
            privateProperty: "I'm hidden"
        };

        privateVars[this._sym] = myPrivateVars;

        this.property = "I'm public";
    }

    getPrivateProperty() {
        return privateVars[this._sym].privateProperty;
    }

    // A clean up method of some kind is necessary since the
    // variables won't be cleaned up from memory automatically
    // when the object is garbage collected
    destroy() {
        delete privateVars[this._sym];
    }
}

var instance = new Something();
console.log(instance.property); //=> "I'm public"
console.log(instance.privateProperty); //=> undefined
console.log(instance.getPrivateProperty()); //=> "I'm hidden"

与使用WeakMap相比,这种方法的潜在优势是,如果需要考虑性能,则访问时间更快。

这取决于你问谁:-)

最大最小类提案中没有包含私有属性修饰符,这似乎已经进入了当前的草案。

但是,可能会支持私有名称,它允许私有属性—而且它们可能也可以用于类定义中。

我用这个模式,它总是对我有效

class Test { constructor(data) { class Public { constructor(prv) { // public function (must be in constructor on order to access "prv" variable) connectToDb(ip) { prv._db(ip, prv._err); } } // public function w/o access to "prv" variable log() { console.log("I'm logging"); } } // private variables this._data = data; this._err = function(ip) { console.log("could not connect to "+ip); } } // private function _db(ip, err) { if(!!ip) { console.log("connected to "+ip+", sending data '"+this.data+"'"); return true; } else err(ip); } } var test = new Test(10), ip = "185.167.210.49"; test.connectToDb(ip); // true test.log(); // I'm logging test._err(ip); // undefined test._db(ip, function() { console.log("You have got hacked!"); }); // undefined