ECMAScript 6 Class 属性下划线前缀
ECMAScript 6 Class properties underscore prefix
我见过的 Class 模式几乎都是这样的:
class Foo {
constructor(x, y, z) {
this._x = x;
this._y = y;
this._z = z;
}
get x() {
return this._x;
}
set x(value) {
//I acctually do some stuff here
this._x = value;
}
get y() {
return this._y;
}
set y(value) {
//I acctually do some stuff here
this._y = value;
}
get z() {
return this._z;
}
set z(value) {
//I acctually do some stuff here
this._z = value;
}
}
console.log(new Foo('x', 'y', 'z'))
执行输出:
Foo { _x: 'x', _y: 'y', _z: 'z' }
console.log(JSON.stringify(new Foo('x', 'y', 'z')))
执行输出:
{"_x":"x","_y":"y","_z":"z"}
这给了我带下划线前缀的字段,而我并不是为了那个,我怎样才能让这些字段没有下划线前缀,并且让 getter 和 setter 由 instance.prop
交互触发。
如果您的问题确实只是下划线,那么您可以尝试使用更类似于 C# 属性的命名约定,其中 get/set 方法使用 PascalCase,但成员变量使用驼峰式命名,如下所示:
class Foo {
constructor(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}
get X() {
return this.x;
}
set X(value) {
this.x = value;
}
get Y() {
return this.y;
}
set Y(value) {
this.y = value;
}
get Z() {
return this.z;
}
set Z(value) {
this.z = value;
}
}
最终,由于对象在 ECMAScript 6 中的工作方式,无法使成员变量和 get/set 方法的命名 100% 相同。事实上,这就是使用下划线格式如此普遍的原因。下划线告诉任何查看代码的人 属性 应该是 "private"。在 ECMAScript 6 中,私有成员的概念并不真正存在。
您可以添加一个toJSON
方法来调整JSON.stringify
的输出
class Foo {
constructor(x, y, z) {
this._x = x;
this._y = y;
this._z = z;
}
get x() {
return this._x;
}
set x(value) {
this._x = value;
}
get y() {
return this._y;
}
set y(value) {
this._y = value;
}
get z() {
return this._z;
}
set z(value) {
this._z = value;
}
toJSON() {
return {
x: this._x,
y: this._y,
z: this._z
};
}
}
var foo = new Foo('x', 'y', 'z');
console.log(JSON.stringify(foo));
输出:"{"x":"x","y":"y","z":"z"}"
如果要跳过下划线属性,将它们定义为不可枚举:
class Foo {
constructor(x, y, z) {
this._x = x;
this._y = y;
this._z = z;
Object.defineProperties(this, {
_x: {enumerable: false},
_y: {enumerable: false},
_z: {enumerable: false}
});
}
get x() { return this._x; }
set x(value) { this._x = value; }
get y() { return this._y; }
set y(value) { this._y = value; }
get z() { return this._z; }
set z(value) { this._z = value; }
}
console.log(JSON.stringify(new Foo('x', 'y', 'z')))
你也可以考虑符号而不是下划线属性:
class Foo {
constructor(x, y, z) {
this[Foo.x] = x;
this[Foo.y] = y;
this[Foo.z] = z;
}
get x() { return this[Foo.x]; }
set x(value) { this[Foo.x] = value; }
get y() { return this[Foo.y]; }
set y(value) { this[Foo.y] = value; }
get z() { return this[Foo.z]; }
set z(value) { this[Foo.z] = value; }
}
Foo.x = Symbol('x');
Foo.y = Symbol('y');
Foo.z = Symbol('z');
console.log(JSON.stringify(new Foo('x', 'y', 'z')))
正如您所说,您想避免在每个 class 中使用 toJSON
(但我也认为使用 toJSON
是 "right" 要做的事情)。
Javascript让你做一些奇怪的事情,但至少你可以在封闭的函数范围内控制它。
我想正则表达式可以改进,但我只是想展示这个想法,虽然不漂亮但应该可以。
class Foo {
constructor(x, y, z) {
this._x = x;
this._y = y;
this._z = z;
}
get x() {
return this._x;
}
set x(value) {
//I acctually do some stuff here
this._x = value;
}
get y() {
return this._y;
}
set y(value) {
//I acctually do some stuff here
this._y = value;
}
get z() {
return this._z;
}
set z(value) {
//I acctually do some stuff here
this._z = value;
}
}
var originalJSON = JSON;
var foo = new Foo('x', 'y', 'z');
(function () {
var JSON = {
stringify: function (obj) {
var json = originalJSON.stringify(obj);
return json.replace(/"_+(\w+)":/g, '"":');
},
parse: function(str) {
return originalJSON.parse(str.replace(/"(\w+)":/g, '"_":'));
}
};
console.log('Weird hack');
var r = JSON.stringify(foo);
console.log('stringify');
console.log(r);
console.log('parse');
console.log(JSON.parse(r));
}).call();
console.log('\nBack to normal');
var r = JSON.stringify(foo);
console.log('stringify');
console.log(r);
console.log('parse');
console.log(JSON.parse(r));
输出:
Weird hack
stringify
{"x":"x","y":"y","z":"z"}
parse
{ _x: 'x', _y: 'y', _z: 'z' }
Back to normal
stringify
{"_x":"x","_y":"y","_z":"z"}
parse
{ _x: 'x', _y: 'y', _z: 'z' }
我见过的 Class 模式几乎都是这样的:
class Foo {
constructor(x, y, z) {
this._x = x;
this._y = y;
this._z = z;
}
get x() {
return this._x;
}
set x(value) {
//I acctually do some stuff here
this._x = value;
}
get y() {
return this._y;
}
set y(value) {
//I acctually do some stuff here
this._y = value;
}
get z() {
return this._z;
}
set z(value) {
//I acctually do some stuff here
this._z = value;
}
}
console.log(new Foo('x', 'y', 'z'))
执行输出:
Foo { _x: 'x', _y: 'y', _z: 'z' }
console.log(JSON.stringify(new Foo('x', 'y', 'z')))
执行输出:
{"_x":"x","_y":"y","_z":"z"}
这给了我带下划线前缀的字段,而我并不是为了那个,我怎样才能让这些字段没有下划线前缀,并且让 getter 和 setter 由 instance.prop
交互触发。
如果您的问题确实只是下划线,那么您可以尝试使用更类似于 C# 属性的命名约定,其中 get/set 方法使用 PascalCase,但成员变量使用驼峰式命名,如下所示:
class Foo {
constructor(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}
get X() {
return this.x;
}
set X(value) {
this.x = value;
}
get Y() {
return this.y;
}
set Y(value) {
this.y = value;
}
get Z() {
return this.z;
}
set Z(value) {
this.z = value;
}
}
最终,由于对象在 ECMAScript 6 中的工作方式,无法使成员变量和 get/set 方法的命名 100% 相同。事实上,这就是使用下划线格式如此普遍的原因。下划线告诉任何查看代码的人 属性 应该是 "private"。在 ECMAScript 6 中,私有成员的概念并不真正存在。
您可以添加一个toJSON
方法来调整JSON.stringify
class Foo {
constructor(x, y, z) {
this._x = x;
this._y = y;
this._z = z;
}
get x() {
return this._x;
}
set x(value) {
this._x = value;
}
get y() {
return this._y;
}
set y(value) {
this._y = value;
}
get z() {
return this._z;
}
set z(value) {
this._z = value;
}
toJSON() {
return {
x: this._x,
y: this._y,
z: this._z
};
}
}
var foo = new Foo('x', 'y', 'z');
console.log(JSON.stringify(foo));
输出:"{"x":"x","y":"y","z":"z"}"
如果要跳过下划线属性,将它们定义为不可枚举:
class Foo {
constructor(x, y, z) {
this._x = x;
this._y = y;
this._z = z;
Object.defineProperties(this, {
_x: {enumerable: false},
_y: {enumerable: false},
_z: {enumerable: false}
});
}
get x() { return this._x; }
set x(value) { this._x = value; }
get y() { return this._y; }
set y(value) { this._y = value; }
get z() { return this._z; }
set z(value) { this._z = value; }
}
console.log(JSON.stringify(new Foo('x', 'y', 'z')))
你也可以考虑符号而不是下划线属性:
class Foo {
constructor(x, y, z) {
this[Foo.x] = x;
this[Foo.y] = y;
this[Foo.z] = z;
}
get x() { return this[Foo.x]; }
set x(value) { this[Foo.x] = value; }
get y() { return this[Foo.y]; }
set y(value) { this[Foo.y] = value; }
get z() { return this[Foo.z]; }
set z(value) { this[Foo.z] = value; }
}
Foo.x = Symbol('x');
Foo.y = Symbol('y');
Foo.z = Symbol('z');
console.log(JSON.stringify(new Foo('x', 'y', 'z')))
正如您所说,您想避免在每个 class 中使用 toJSON
(但我也认为使用 toJSON
是 "right" 要做的事情)。
Javascript让你做一些奇怪的事情,但至少你可以在封闭的函数范围内控制它。
我想正则表达式可以改进,但我只是想展示这个想法,虽然不漂亮但应该可以。
class Foo {
constructor(x, y, z) {
this._x = x;
this._y = y;
this._z = z;
}
get x() {
return this._x;
}
set x(value) {
//I acctually do some stuff here
this._x = value;
}
get y() {
return this._y;
}
set y(value) {
//I acctually do some stuff here
this._y = value;
}
get z() {
return this._z;
}
set z(value) {
//I acctually do some stuff here
this._z = value;
}
}
var originalJSON = JSON;
var foo = new Foo('x', 'y', 'z');
(function () {
var JSON = {
stringify: function (obj) {
var json = originalJSON.stringify(obj);
return json.replace(/"_+(\w+)":/g, '"":');
},
parse: function(str) {
return originalJSON.parse(str.replace(/"(\w+)":/g, '"_":'));
}
};
console.log('Weird hack');
var r = JSON.stringify(foo);
console.log('stringify');
console.log(r);
console.log('parse');
console.log(JSON.parse(r));
}).call();
console.log('\nBack to normal');
var r = JSON.stringify(foo);
console.log('stringify');
console.log(r);
console.log('parse');
console.log(JSON.parse(r));
输出:
Weird hack
stringify
{"x":"x","y":"y","z":"z"}
parse
{ _x: 'x', _y: 'y', _z: 'z' }
Back to normal
stringify
{"_x":"x","_y":"y","_z":"z"}
parse
{ _x: 'x', _y: 'y', _z: 'z' }