JavaScript 中是否有任何 linter 警告副作用?
Any linter to warn about side-effects in JavaScript?
凭借 JavaScript 的灵活性,我们可以编写充满副作用的代码,或者仅仅是功能性的代码。
我一直对函数式 JavaScript 很感兴趣,并且想在这个范例中开始一个项目。一个关于它的 linter 肯定可以帮助我收集好的实践。是否有任何 linter 来强制执行纯功能和无副作用的风格?
我自己没用过这个,但我发现了这个 ESLint 插件:https://github.com/jfmengels/eslint-plugin-fp
纯度分析相当于Solving the Halting Problem,所以任何一种可以判断代码是纯的还是不纯的静态分析在一般情况下都是不可能的。总会有无穷多的程序,它们是否是纯的是不可判定的;其中一些程序是纯净的,一些是不纯净的。
现在,您故意使用术语 "linter" 而不是静态分析器(尽管 linter 当然只是静态分析器),这似乎暗示您可以接受近似的启发式结果。您 可以 有一个 linter 有时会告诉您您的代码是纯的,有时会告诉您您的代码是不纯的,并且大多数时候会告诉您它无法决定您的代码是纯的还是不纯。您可以拥有一个已知为纯操作的白名单(例如,使用 +
运算符添加两个 Number
),以及一个已知为不纯操作的黑名单(例如,任何可以抛出异常,任何类型的循环,if
语句,Array.prototype.forEach
) 并对这些进行启发式扫描。
但最后,结果会太不可靠,无法对其进行任何认真的处理。
没有副作用就不能完全使用JS。每个 DOM-access 都是副作用,我们可以争论整个全局命名空间是否也属于该定义。
你能做的最好的事情就是保持理性。我在逻辑上将其分为两组:
工作马(实用程序):它们的目的是获取一些数据并以某种方式处理它。这些 (大部分) 无副作用。大多数情况下,因为有时这些函数需要一些状态,比如计数器或缓存,这可能会被认为是副作用,但由于这是 isolated/enclosed 这些函数我并不关心。
就像你传递给 Array#map()
或承诺 then()
以及类似地方的函数。
和管理:这些功能很少自己做一些 data-processing,它们主要协调数据流,从创建它的任何地方到它具有的任何处理(-实用程序)成为 运行,直到结束,例如修改 DOM 或改变对象。
var theOnesINeed = compose(...);
var theOtherOnesINeed = compose(...);
var intoADifferentFormat = function(value){ return ... }
function(event){
var a = someList.filter(theOnesINeed).map(intoADifferentFormat);
var b = someOtherList.filter(theOtherOnesINeed);
var rows = a.concat(b).map(wrap('<li>', '</li>'));
document.querySelector('#youYesYou').innerHTML = rows.join('\n');
}
让所有功能都尽可能简短。并且不要害怕描述性名称(不像一般名称那样:))
凭借 JavaScript 的灵活性,我们可以编写充满副作用的代码,或者仅仅是功能性的代码。
我一直对函数式 JavaScript 很感兴趣,并且想在这个范例中开始一个项目。一个关于它的 linter 肯定可以帮助我收集好的实践。是否有任何 linter 来强制执行纯功能和无副作用的风格?
我自己没用过这个,但我发现了这个 ESLint 插件:https://github.com/jfmengels/eslint-plugin-fp
纯度分析相当于Solving the Halting Problem,所以任何一种可以判断代码是纯的还是不纯的静态分析在一般情况下都是不可能的。总会有无穷多的程序,它们是否是纯的是不可判定的;其中一些程序是纯净的,一些是不纯净的。
现在,您故意使用术语 "linter" 而不是静态分析器(尽管 linter 当然只是静态分析器),这似乎暗示您可以接受近似的启发式结果。您 可以 有一个 linter 有时会告诉您您的代码是纯的,有时会告诉您您的代码是不纯的,并且大多数时候会告诉您它无法决定您的代码是纯的还是不纯。您可以拥有一个已知为纯操作的白名单(例如,使用 +
运算符添加两个 Number
),以及一个已知为不纯操作的黑名单(例如,任何可以抛出异常,任何类型的循环,if
语句,Array.prototype.forEach
) 并对这些进行启发式扫描。
但最后,结果会太不可靠,无法对其进行任何认真的处理。
没有副作用就不能完全使用JS。每个 DOM-access 都是副作用,我们可以争论整个全局命名空间是否也属于该定义。
你能做的最好的事情就是保持理性。我在逻辑上将其分为两组:
工作马(实用程序):它们的目的是获取一些数据并以某种方式处理它。这些 (大部分) 无副作用。大多数情况下,因为有时这些函数需要一些状态,比如计数器或缓存,这可能会被认为是副作用,但由于这是 isolated/enclosed 这些函数我并不关心。
就像你传递给Array#map()
或承诺then()
以及类似地方的函数。和管理:这些功能很少自己做一些 data-processing,它们主要协调数据流,从创建它的任何地方到它具有的任何处理(-实用程序)成为 运行,直到结束,例如修改 DOM 或改变对象。
var theOnesINeed = compose(...); var theOtherOnesINeed = compose(...); var intoADifferentFormat = function(value){ return ... } function(event){ var a = someList.filter(theOnesINeed).map(intoADifferentFormat); var b = someOtherList.filter(theOtherOnesINeed); var rows = a.concat(b).map(wrap('<li>', '</li>')); document.querySelector('#youYesYou').innerHTML = rows.join('\n'); }
让所有功能都尽可能简短。并且不要害怕描述性名称(不像一般名称那样:))