【问题标题】:Why is using side effects bad practice in JavaScript constructors?为什么在 JavaScript 构造函数中使用副作用是不好的做法?
【发布时间】:2013-01-19 15:20:16
【问题描述】:

我通常在我的代码中使用与设计模式custom objects 非常相似的东西。

但是 JSLint 不赞成这样的结构:

function MyClass() { this.init(); }
new MyClass(data);

因为对象在创建后立即被丢弃 - 它没有被用于任何事情。 我们可以通过将它分配给一个变量来欺骗 JSLint 忽略它,但这并没有改变 JSLint(我猜很多 JavaScript 爱好者)不鼓励这种模式。

那么为什么在 JavaScript 构造函数中使用副作用被视为一种不好的做法呢?

对于它的价值,我认为这是一个好的做法,因为:

  1. 您只有一个设置功能,因此它应该更容易维护,例如您正在管理 MyClass 实例列表以供以后访问。 (将对象推入数组是一种副作用,您必须在构造函数返回为“良好做法”= 更难维护之后再执行此操作。)
  2. 它有自己的原型,因此是“类所有权”:Firebug 将其报告为 MyClass 的实例,而不仅仅是 Object。 (在我看来,这使它优于其他设计模式。)

【问题讨论】:

  • JSLint 不鼓励new MyClass,因为您在实例化它之后就没有使用它。因此,它仅用于其副作用。相反,这个例子可以重写为initialize(new MyClass()); 使用依赖注入(虽然这个例子简单到很傻)。
  • 你真的从来没有将新创建的MyClass 实例分配给任何东西(换句话说,这是使init() 成为一种静态方法的复杂方法)? “正常”使用此模式不会触发 JSLint 警告。
  • @FrédéricHamidi 不是从来没有,但有时它会产生副作用,它本身就可以完成这项工作,即没有什么需要做的了。 Person 构造函数可能会实例化一个人对象,但您现在可能不一定需要对该人进行操作。如果您确实需要,副作用会在数组中注册以供以后访问。
  • @zzzzBov JSLint 的警告是相当误导,如果不鼓励副作用但只使用它们来产生副作用。警告内容为“不要使用‘新的’来产生副作用。”我可能弄错了,但对我来说,这意味着它必须专门用于设置属性(或用于继承)。
  • 构造函数可用于执行功能,只是希望您做的不仅仅是实例化构造函数。如果您所做的只是实例化一个对象并丢弃它,那么您最好使用普通的函数调用。

标签: javascript coding-style constructor


【解决方案1】:

罗伯特·马丁在他的书清洁代码中说

副作用是谎言。你的函数承诺做一件事,但它 还做其他隐藏的事情......它们是狡猾和破坏性的错误,通常会导致奇怪的时间耦合和顺序依赖。

您在评论中关于数组的描述听起来像是“奇怪的时间耦合”。

【讨论】:

  • 有用的答案,感谢搜索词和参考资料。我发现这与任何有类似问题的人有关 - Mark Seemann's .NET blog(不使用 JavaScript)。没有更好的答案,我会接受这个。
猜你喜欢
  • 1970-01-01
  • 2011-03-19
  • 2013-08-23
  • 1970-01-01
  • 2015-09-22
  • 2012-06-01
  • 2010-09-23
  • 2018-11-15
  • 1970-01-01
相关资源
最近更新 更多