【问题标题】:ECMAScript 6 Class properties underscore prefixECMAScript 6 类属性下划线前缀
【发布时间】:2017-03-17 09:20:03
【问题描述】:

我见过的类模式几乎是这样的:

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"}

这给了我下划线前缀的字段,而我的目标不是这个,我怎样才能让字段没有下划线前缀,但是,有由instance.prop 交互触发的 getter 和 setter。

【问题讨论】:

  • 我会说从变量后面删除 _ ?喜欢constructor(x, y, z) { this.x = x; this.y = y; this.z = z; }
  • 是的,在此示例中,与直接分配属性并跳过 getter 相比,优势为零。
  • @loganfsmyth 对不起这个糟糕的例子,但我实际上在我的real world application 中使用自定义设置器来设置属性,为了更好地理解,我编辑了我的 sn-p。
  • 你用这个 JSON 数据做什么?我会说通常你不应该依赖类的 JSON 自动序列化,如果某物是一个类,你应该有一个方法,显式地或通过 .toJSON 获取它的可序列化对象版本。
  • @loganfsmyth 现在,我只是使用本机驱动程序将数据保存在 mongodb 上(使用下划线保存属性),并在暴露的 JSON API 中返回它(在这种情况下,我使用 @987654330 @ 仅适用于我想省略我不想在前端结束的字段的类,例如密码)。

标签: javascript node.js ecmascript-6 es6-class


【解决方案1】:

如果您的问题确实只是下划线,那么您可以尝试使用更类似于 C# 属性的命名约定,其中 get/set 方法使用 PascalCase 但成员变量使用 camelCase,如下所示:

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% 相同。事实上,这就是为什么使用下划线格式如此普遍的原因。下划线告诉任何查看代码的人该属性是“私有的”。在 ECMAScript 6 中,私有成员的概念并不真正存在。

【讨论】:

  • 虽然你的语法可能不是我想要的,但你的答案非常重要,因为我一直在努力尝试这个Ultimately, due to how objects work in ECMAScript 6 there is no way to have both the member variable and get/set methods named 100% the same.,现在我可以放心并继续前进,用一个你们在这里介绍的许多方式。谢谢!
【解决方案2】:

可以添加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"}"

【讨论】:

  • 我在几个例子中看到了这个,但我必须在每次使用我的课程时都使用它,所以我避免使用它,但感谢您的参考!
【解决方案3】:

如果你想跳过下划线属性,将它们定义为不可枚举:

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')))

【讨论】:

  • 两个 sn-ps 都返回了空对象 D: 甚至还给你投票了,兄弟,你怎么能呢?哈哈哈
  • 它们不是空的。他们只是没有自己的可枚举字符串属性。
【解决方案4】:

正如您所说,您希望避免在每个课程中使用toJSON(但我也认为使用toJSON 是“正确”的做法)。

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, '"$1":');
    },
    parse: function(str) {
      return originalJSON.parse(str.replace(/"(\w+)":/g, '"_$1":'));
    }
  };

  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' }

【讨论】:

    猜你喜欢
    • 2011-07-31
    • 1970-01-01
    • 2011-09-03
    • 1970-01-01
    • 2015-02-12
    • 2017-09-13
    • 2011-08-24
    • 2017-07-26
    相关资源
    最近更新 更多