是否可以在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"
当前回答
WeakMap
IE11支持(符号不支持) hard-private(由于Object.getOwnPropertySymbols,使用符号的道具是soft-private) 看起来非常干净(不像闭包需要构造函数中的所有道具和方法)
首先,定义一个函数来包装WeakMap:
function Private() {
const map = new WeakMap();
return obj => {
let props = map.get(obj);
if (!props) {
props = {};
map.set(obj, props);
}
return props;
};
}
然后,在类外部构造一个引用:
const p = new Private();
class Person {
constructor(name, age) {
this.name = name;
p(this).age = age; // it's easy to set a private variable
}
getAge() {
return p(this).age; // and get a private variable
}
}
注意:IE11不支持class,但在示例中它看起来更简洁。
其他回答
更新:看别人的回答,这个已经过时了。
简单的回答,不,ES6类不支持私有属性。
但是你可以模仿这种行为,不将新属性附加到对象,而是将它们保存在类构造函数中,并使用getter和setter来获取隐藏的属性。注意,在类的每个新实例上重新定义getter和setter。
ES6
class Person {
constructor(name) {
var _name = name
this.setName = function(name) { _name = name; }
this.getName = function() { return _name; }
}
}
ES5
function Person(name) {
var _name = name
this.setName = function(name) { _name = name; }
this.getName = function() { return _name; }
}
你可以试试这个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;
这取决于你问谁:-)
最大最小类提案中没有包含私有属性修饰符,这似乎已经进入了当前的草案。
但是,可能会支持私有名称,它允许私有属性—而且它们可能也可以用于类定义中。
实际上这是可能的。 1. 首先,创建类,并在构造函数中返回被调用的_public函数。 2. 在被调用的_public函数中传递this引用(以获得对所有私有方法和道具的访问),以及构造函数的所有参数(将在new Names()中传递) 3.在_public函数作用域中,还有一个Names类,它可以访问私有Names类的this (_this)引用
class Names {
constructor() {
this.privateProperty = 'John';
return _public(this, arguments);
}
privateMethod() { }
}
const names = new Names(1,2,3);
console.log(names.somePublicMethod); //[Function]
console.log(names.publicProperty); //'Jasmine'
console.log(names.privateMethod); //undefined
console.log(names.privateProperty); //undefind
function _public(_this, _arguments) {
class Names {
constructor() {
this.publicProperty = 'Jasmine';
_this.privateProperty; //"John";
_this.privateMethod; //[Function]
}
somePublicMethod() {
_this.privateProperty; //"John";
_this.privateMethod; //[Function]
}
}
return new Names(..._arguments);
}
事实上,使用符号和代理是可能的。您可以使用类作用域中的符号,并在代理中设置两个陷阱:一个用于类原型,以便Reflect.ownKeys(实例)或Object。getOwnPropertySymbols不会泄露你的符号,另一个是构造函数本身,所以当调用new ClassName(attrs)时,返回的实例将被拦截,并有自己的属性符号被阻塞。 代码如下:
const Human = (function() { const pet = Symbol(); const greet = Symbol(); const Human = privatizeSymbolsInFn(function(name) { this.name = name; // public this[pet] = 'dog'; // private }); Human.prototype = privatizeSymbolsInObj({ [greet]() { // private return 'Hi there!'; }, revealSecrets() { console.log(this[greet]() + ` The pet is a ${this[pet]}`); } }); return Human; })(); const bob = new Human('Bob'); console.assert(bob instanceof Human); console.assert(Reflect.ownKeys(bob).length === 1) // only ['name'] console.assert(Reflect.ownKeys(Human.prototype).length === 1 ) // only ['revealSecrets'] // Setting up the traps inside proxies: function privatizeSymbolsInObj(target) { return new Proxy(target, { ownKeys: Object.getOwnPropertyNames }); } function privatizeSymbolsInFn(Class) { function construct(TargetClass, argsList) { const instance = new TargetClass(...argsList); return privatizeSymbolsInObj(instance); } return new Proxy(Class, { construct }); }
Reflect.ownKeys()是这样工作的:Object.getOwnPropertyNames(myObj).concat(Object.getOwnPropertySymbols(myObj))这就是为什么我们需要为这些对象设置一个陷阱。