是否可以在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"
当前回答
我找到了一个非常简单的解决方案,只需使用Object.freeze()。当然,问题是以后你不能向对象添加任何东西。
class Cat {
constructor(name ,age) {
this.name = name
this.age = age
Object.freeze(this)
}
}
let cat = new Cat('Garfield', 5)
cat.age = 6 // doesn't work, even throws an error in strict mode
其他回答
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"
实际上这是可能的。 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);
}
读了前面的答案,我认为这个例子可以总结以上的解决方案
const friend = Symbol('friend');
const ClassName = ((hidden, hiddenShared = 0) => {
class ClassName {
constructor(hiddenPropertyValue, prop){
this[hidden] = hiddenPropertyValue * ++hiddenShared;
this.prop = prop
}
get hidden(){
console.log('getting hidden');
return this[hidden];
}
set [friend](v){
console.log('setting hiddenShared');
hiddenShared = v;
}
get counter(){
console.log('getting hiddenShared');
return hiddenShared;
}
get privileged(){
console.log('calling privileged method');
return privileged.bind(this);
}
}
function privileged(value){
return this[hidden] + value;
}
return ClassName;
})(Symbol('hidden'), 0);
const OtherClass = (() => class OtherClass extends ClassName {
constructor(v){
super(v, 100);
this[friend] = this.counter - 1;
}
})();
更新
现在有可能使真正的私有属性和方法(至少在基于chrome的浏览器现在)。
语法非常简洁
class MyClass {
#privateProperty = 1
#privateMethod() { return 2 }
static #privateStatic = 3
static #privateStaticMethod(){return 4}
static get #privateStaticGetter(){return 5}
// also using is quite straightforward
method(){
return (
this.#privateMethod() +
this.#privateProperty +
MyClass.#privateStatic +
MyClass.#privateStaticMethod() +
MyClass.#privateStaticGetter
)
}
}
new MyClass().method()
// returns 15
注意,对于检索静态引用,不能使用this.constructor。#private,因为它会终止它的子类。你必须使用一个对适当类的引用来检索它的静态私有引用(只能在该类的方法中使用),即MyClass.#private。
根据ES2022,我们可以在JavaScript类中添加私有属性和方法。
我们可以通过在私有字段的名称前预先挂起#来定义它们。
演示:
类Something { #property = "test";//通过在属性名后面加上#,我们使它成为私有的。 } var instance = new Something(); console.log(实例。#产权);私有字段'#property'必须在一个外围类中声明
答案是“不”。但是你可以像这样创建对属性的私有访问:
使用模块。模块中的所有内容都是私有的,除非使用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)