你能在不使用它的情况下改变工厂函数的属性吗?

Can you mutate the properties of a factory function without using this?

我一直在阅读关于使用工厂函数优于 classes 的好处,但是,我无法让它们以类似的方式工作。

例如,classes:

class NumberManager {
    constructor(numbers){
        this.numbers = numbers;
    }

    removeNumber(input){ 
        this.numbers = this.numbers.filter( number => number != input )
    }
}

n = new NumberManager([1, 2])
n.numbers // --> [1, 2]
n.removeNumber(2)
n.numbers // --> [1]

但是,使用工厂函数:

const NumberFactory = (numbers) => {
  const removeNumber = (input) => {
    numbers = numbers.filter( number => number != input )
  }

  return {
    numbers,
    removeNumber
  }
}

n = NumberFactory([1, 2])
n.numbers // --> [1, 2]
n.removeNumber(2)
n.numbers // --> [1, 2]

是否有可能拥有与 classes 相似的自由度(例如,轻松改变属性),而不必使用像 this 这样的东西(它可以打破执行上下文)和new(如果必须将 class 转换为工厂,这可能会中断)?

在 return 之前将您想要从工厂 return 的对象放入变量中,然后您可以引用该变量并改变对象:

const NumberFactory = (numbers) => {
  const removeNumber = (input) => {
    instance.numbers = instance.numbers.filter( number => number != input );
  };
  const instance = { numbers, removeNumber };

  return instance;
}

const n = NumberFactory([1, 2]);
console.log(n.numbers); // --> [1, 2]
n.removeNumber(2);
console.log(n.numbers); // --> [1]

除了 @CertainPerformance's ,您还可以为数字变量公开一个 getter(也许还有一个 setter):

const NumberFactory = (numbers) => {
  const removeNumber = (input) => {
    numbers = numbers.filter( number => number != input );
  };
  return {
    get numbers(){ return numbers }, 
    // And if you want to allow external replacement of numbers:
    // set numbers(value){ numbers = value },
    removeNumber 
  };
}

const n = NumberFactory([1, 2]);
console.log(n.numbers); // --> [1, 2]
n.removeNumber(2);
console.log(n.numbers); // --> [1]

或者只是改变数组(使用突变方法而不是 filter):

const NumberFactory = (numbers) => {
  const removeNumber = (input) => {
    for(let i = 0; i < numbers.length; ){ // <-- Note that we don't increment i here
      if(numbers[i] != input) // <-- Condition goes here
        i++
      else
        numbers.splice(i, 1)
    }
  };
  return {
    numbers,
    removeNumber 
  };
}

const n = NumberFactory([1, 2]);
console.log(n.numbers); // --> [1, 2]
n.removeNumber(2);
console.log(n.numbers); // --> [1]