【问题标题】:Having issues making static fields (non-method, primitive) in an ES6 class?在 ES6 类中创建静态字段(非方法、原始)时遇到问题?
【发布时间】:2017-05-30 06:44:05
【问题描述】:

我想创建一个BankAccount 类,其中一个新实例跟踪新实例的检查和保存。但是,每当有人创建一个新实例时,我想要一个静态方法来调用一个静态字段,该字段仅与 BankAccount 类相关联,它可以跟踪打开的银行账户数量(有点像单身人士的行为) .这在 c#/java 中是可行的,但很难在 Javascript 中重新创建预期的行为。

我也在 E​​S5 中尝试过,但结果很短,这是我使用函数作为包装器来封装的最接近的行为:

function BankAccountMaker() {
    var countOfAccounts = 0;
    function IncrementcountOfAccounts() {
        countOfAccounts += 1;
    }

    function BankAccount(c = 0) {
        this.checking = 0;
    }

    return {
        makeBankAccount: function (c) {
            IncrementcountOfAccounts();
            console.log(countOfAccounts)
            return new BankAccount(c);
        }
    }
}

最后,几个问题:

  1. 有人可以编写与上述等效的 ES6 代码吗?
  2. 另外,在不需要包装器的 ES5 中有没有更好的方法来做到这一点?
  3. 为什么在 ES5 中我们可以将原型方法设置为原始方法,但使用 ES6 语法似乎无法做到这一点? (我使用的是 Node 6.1 和 Babel fwiw)

【问题讨论】:

  • 仅与 BankAccount 类相关的静态字段,用于跟踪打开的银行账户数量” - 不要。这正是(全局/静态,可变)单例不好的原因。它泄漏内存并且是非模块化的(不可测试的)。在创建实例的方法中保留跟踪记录。就像您对 BankAccountMaker 所做的一样。
  • "为什么在 ES5 中我们可以将原型方法设置为原始方法,但使用 ES6 语法似乎无法做到这一点?" - 请单独询问对此提出问题,并为您的意思提供示例代码。顺便说一句,方法不是原语。
  • 对代码的改进:1) 内联 IncrementcountOfAccounts 2) 将 BankAccount 放在 BankAccountMaker 之外,这不是需要访问计数的闭包 - 这将避免重新创建相同的类.然后将其转换为 ES6,只需将 BankAccount 设为 class

标签: javascript ecmascript-6 es6-class


【解决方案1】:

我已为每个银行帐户添加了一个 ID。因此,您可以遍历您创建的帐户。 incrementcountAccounts 是个坏主意,因为您不知道是否真的创建了银行帐户。

你不能这样做:BankAccount(c = 0) 参数在 ES5 中不受支持。

一些sn-ps:

/**
 * Bank
 */
class Bank {
  constructor(name, id) {
    this.countOfAccounts = 0;
    this.id = id;
    this.name = name;
    
    console.log('--- ' + this.name + ' ---');
  }

  incrementcountOfAccounts() {
    this.countOfAccounts += 1;
  }
  
  addBankAccount(...data) {
    this.incrementcountOfAccounts();
    
    return new BankAccount(this.id, ...data);
  }
}

/**
 * BankAccount
 */
class BankAccount {
  /**
   * Constrctor
   * @param  {Number} bankId     
   * @param  {Number} [amount=0]   
   * @param  {Number} [checking=0]            
   */
  constructor(bankId, amount = 0, checking = 0) {
    if(!bankId) {
      throw Error('no bank id');
    }
    
    this.account = {
      bankId,
      checking, 
      amount
    };
  }
  
  /**
   * Get bank id
   * @return {number}
   */
  get bankId() {
    return this.account.bankId;
  }

  /**
   * Set amount
   * @param  {number} value
   * @return {number}       
   */
  set amount(value) {
    this.account.amount = value;
  }  

  /**
   * Get ammunt
   * @return {number}
   */
  get amount() {
    return this.account.amount;
  }

  /**
   * set checking
   * @param  {number} value
   * @return {number}     
   */
  set checking(value) {
    this.account.checking = value;
  }  

  /**
   * get checking
   * @return {number} 
   */
  get checking() {
    return this.account.checking;
  }
}

const FirstBank = new Bank('First Bank', 1);


const bankAccount1 = FirstBank.addBankAccount(300);
const bankAccount2 = FirstBank.addBankAccount(4000);


console.log('Account 1: ' + bankAccount1.amount + ' - ' + bankAccount1.checking + ' - ' + bankAccount1.bankId);
console.log('Account 2: ' + bankAccount2.amount + ' - ' + bankAccount1.checking + ' - ' + bankAccount1.bankId);


console.log('Accounts first Bank: ' + FirstBank.countOfAccounts);

const SecondBank = new Bank('Second Bank', 4);
const bankAccount3 = SecondBank.addBankAccount(0, 1);
console.log('Account 3: ' + bankAccount3.amount + ' - ' + bankAccount1.checking + ' - ' + bankAccount1.bankId);    
console.log('Accounts second Bank: ' + SecondBank.countOfAccounts);

ES5:

var BankAccountMaker = function () {
  this.countOfAccounts = 0;
  
  this.IncrementcountOfAccounts = function () {
    this.countOfAccounts += 1;
  }
  
  this.BankAccount = function () {
    this.checking = 0;
  }
  
  this.makeBankAccount = function (c) {
    this.IncrementcountOfAccounts();

    return new this.BankAccount(c);
  }
}

const Bank = new BankAccountMaker();

console.log(Bank.makeBankAccount(3));
console.log(Bank.makeBankAccount(3));
console.log(Bank.makeBankAccount(3));
console.log(Bank.countOfAccounts);

ES5 原型:

function BankAccountMaker() {
  this.countOfAccounts = 0;

}

BankAccountMaker.prototype.IncrementcountOfAccounts = function() {
  this.countOfAccounts += 1;
}

BankAccountMaker.prototype.BankAccount = function() {
  this.checking = 0;
}

BankAccountMaker.prototype.IncrementcountOfAccounts = function() {
  this.countOfAccounts += 1;
}

BankAccountMaker.prototype.makeBankAccount = function(c) {
  this.IncrementcountOfAccounts();
  console.log(this.countOfAccounts);
  
  return new this.BankAccount(c);
}

const Bank = new BankAccountMaker();

console.log(Bank.makeBankAccount(3));
console.log(Bank.makeBankAccount(3));
console.log(Bank.makeBankAccount(3));
console.log(Bank.countOfAccounts);

【讨论】:

  • 感谢您的详细记录。我想我在最初的问题中没有很好地表达出来——我正在寻找的是一个静态字段行为,就像你在 C#/Java 中找到的那样。也就是说,根据您提供的答案以及 Bergi,这不是 ES6 语言中的功能。
猜你喜欢
  • 2016-09-19
  • 2015-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-17
  • 1970-01-01
相关资源
最近更新 更多