是否可以在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"
当前回答
甚至Typescript也做不到。从他们的文档来看:
当成员被标记为private时,就不能从其包含类的外部访问它。例如: 动物类{ 私有名称:字符串; 构造函数(名称:字符串){this.name =名称;} } 新的动物(猫). name;//错误:'name'是private;
但在他们的操场上,这说明:
var Animal = (function () {
function Animal(theName) {
this.name = theName;
}
return Animal;
}());
console.log(new Animal("Cat").name);
所以他们的“私人”关键字是无效的。
其他回答
这取决于你问谁:-)
最大最小类提案中没有包含私有属性修饰符,这似乎已经进入了当前的草案。
但是,可能会支持私有名称,它允许私有属性—而且它们可能也可以用于类定义中。
Yes totally can, and pretty easily too. This is done by exposing your private variables and functions by returning the prototype object graph in the constructor. This is nothing new, but take a bit of js foo to understand the elegance of it. This way does not use global scoped, or weakmaps. It is a form of reflection built into the language. Depending on how you leverage this; one can either force an exception which interrupts the call stack, or bury the exception as an undefined. This is demonstarted below, and can read more about these features here
class Clazz { constructor() { var _level = 1 function _private(x) { return _level * x; } return { level: _level, public: this.private, public2: function(x) { return _private(x); }, public3: function(x) { return _private(x) * this.public(x); }, }; } private(x) { return x * x; } } var clazz = new Clazz(); console.log(clazz._level); //undefined console.log(clazz._private); // undefined console.log(clazz.level); // 1 console.log(clazz.public(1)); //1 console.log(clazz.public2(2)); //2 console.log(clazz.public3(3)); //27 console.log(clazz.private(0)); //error
我有一个解决办法,它很简单…虽然性能不是问题…但它确实有效,而且效果很好。
诀窍在于,在私有属性和函数被建立和标准化/采用之前,需要另一种解决方案,这是另一种解决方案…
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'));
就像我提到的,这个问题不是最好的,但它工作,使属性真正的私有。
哦,这么多奇异的解决方案!我通常不关心隐私,所以我使用“伪隐私”,正如这里所说的。但如果确实关心(如果有一些特殊的要求),我会在这个例子中使用:
class jobImpl{
// public
constructor(name){
this.name = name;
}
// public
do(time){
console.log(`${this.name} started at ${time}`);
this.prepare();
this.execute();
}
//public
stop(time){
this.finish();
console.log(`${this.name} finished at ${time}`);
}
// private
prepare(){ console.log('prepare..'); }
// private
execute(){ console.log('execute..'); }
// private
finish(){ console.log('finish..'); }
}
function Job(name){
var impl = new jobImpl(name);
return {
do: time => impl.do(time),
stop: time => impl.stop(time)
};
}
// Test:
// create class "Job"
var j = new Job("Digging a ditch");
// call public members..
j.do("08:00am");
j.stop("06:00pm");
// try to call private members or fields..
console.log(j.name); // undefined
j.execute(); // error
函数(构造函数)的另一种可能实现:
function Job(name){
var impl = new jobImpl(name);
this.do = time => impl.do(time),
this.stop = time => impl.stop(time)
}
这段代码演示了私有和公共、静态和非静态、实例级和类级、变量、方法和属性。
https://codesandbox.io/s/class-demo-837bj
class Animal { static count = 0 // class static public static #ClassPriVar = 3 // class static private constructor(kind) { this.kind = kind // instance public property Animal.count++ let InstancePriVar = 'InstancePriVar: ' + kind // instance private constructor-var log(InstancePriVar) Animal.#ClassPriVar += 3 this.adhoc = 'adhoc' // instance public property w/out constructor- parameter } #PawCount = 4 // instance private var set Paws(newPawCount) { // instance public prop this.#PawCount = newPawCount } get Paws() { // instance public prop return this.#PawCount } get GetPriVar() { // instance public prop return Animal.#ClassPriVar } static get GetPriVarStat() { // class public prop return Animal.#ClassPriVar } PrintKind() { // instance public method log('kind: ' + this.kind) } ReturnKind() { // instance public function return this.kind } /* May be unsupported get #PrivMeth(){ // instance private prop return Animal.#ClassPriVar + ' Private Method' } static get #PrivMeth(){ // class private prop return Animal.#ClassPriVar + ' Private Method' } */ } function log(str) { console.log(str) } // TESTING log(Animal.count) // static, avail w/out instance log(Animal.GetPriVarStat) // static, avail w/out instance let A = new Animal('Cat') log(Animal.count + ': ' + A.kind) log(A.GetPriVar) A.PrintKind() A.Paws = 6 log('Paws: ' + A.Paws) log('ReturnKind: ' + A.ReturnKind()) log(A.adhoc) let B = new Animal('Dog') log(Animal.count + ': ' + B.kind) log(B.GetPriVar) log(A.GetPriVar) // returns same as B.GetPriVar. Acts like a class-level property, but called like an instance-level property. It's cuz non-stat fx requires instance. log('class: ' + Animal.GetPriVarStat) // undefined log('instance: ' + B.GetPriVarStat) // static class fx log(Animal.GetPriVar) // non-stat instance fx log(A.InstancePriVar) // private log(Animal.InstancePriVar) // private instance var log('PawCount: ' + A.PawCount) // private. Use getter /* log('PawCount: ' + A.#PawCount) // private. Use getter log('PawCount: ' + Animal.#PawCount) // Instance and private. Use getter */