JavaScript 函数参数的最佳实践 | CodeUtopia
cchm0236
8年前
<p>常常会有人问一些像“我应该使用对象来传递函数参数吗”这类问题。我确定你知道这种模式,因为这在许多库中很常见:</p> <pre> <code class="language-javascript">$.post({ a: 'lot', of: 'properties', live: 'in', here: 'yep' })`</code></pre> <p>但是我想说,这实际上不是一个好主意。</p> <p>让我们看看再 JavaScript 中定义函数参数列表最佳的实践。</p> <h3>清晰是目标</h3> <p>把对象当作参数传递给函数的问题是你要传入的值指向不清。</p> <p>像jQuery这样的库,这不是一个大问题——就是看看文档然后就知道你要怎么做了。但是在自定义代码中,你会在工作中碰到?看看文档……啊!等等!哪来的文档!Yeah。</p> <p>尽可能多的文档当然好,自定义代码库永远不会有这种你需要的文档。如果你需要弄清一些方法需要的参数,你需要深入了解源代码。</p> <p>这个问题可以用一个例子来解释。这里有一个用于控制其他函数之间间隔的函数。</p> <pre> <code class="language-javascript">function throttle(o) { o.threshhold || (o.threshhold = 250); var last, deferTimer; return function () { var context = o.scope || this; var now = +new Date, args = arguments; if (last && now < last + threshhold) { // hold on to it clearTimeout(deferTimer); deferTimer = setTimeout(function () { last = now; o.fn.apply(context, args); }, o.threshhold); } else { last = now; o.fn.apply(context, args); } }; }</code></pre> <p>快!你往参数对象中放入了什么值?</p> <p>没有浏览整个函数的话,你是找不到关于参数的恼人线索的,甚至之后,你可能会出错。</p> <p>这里是原始的注释:</p> <pre> <code class="language-javascript">function throttle(fn, threshhold, scope)`</code></pre> <p>快!函数取了什么参数??</p> <p>如果你拆解了这个炸弹,然后你需要回答那个问题或者爆炸,并且你只有几秒钟的时间思考……我肯定具有独立的参数会比较好。</p> <p>好啦,那么第一个最佳尝试是:给你的函数使用单独命名的参数</p> <p>此外,单独的参数如果在一个函数式编程风格中同样很有帮助。在FP中一个常见的事是调用函数,如果你的函数使用对象作为参数,那么会非常苦逼。</p> <h3>对于可选项来说对象非常好</h3> <p>单独的参数是一个很好的开始,那么我们将会在函数有可选参数的时候遇到问题。</p> <p>对于只有一个可选参数的函数来说,解决方案很简单:</p> <p>function stuff(requiredA, requiredB, optional)</p> <p>最佳实践:可选项放在最后</p> <p>然而,如果你有多于一个的可选项,问题……如果我们只传 <em>一</em> 个可选参数如何?</p> <pre> <code class="language-javascript">function foo(required, optionalA, optionalB) { /* something */ } foo('hello', undefined, 1337);</code></pre> <p>啊!需要填充类似于undefined的值,这真的是越来越复杂了——同样需要调用他们,并且需要在函数中处理这些参数</p> <p>在多可选参数的情况下,我们可以使用对象。这并没有真正地解决问题,但是这意味着我们不需要处理额外的值。</p> <p>foo('hello', { optionalB: 1337 });</p> <p>最佳实践:如果有超过一个可选参数时,使用对象</p> <h3>ES6的好处</h3> <p>最后,如果你使用ES6或者TypeScript,我们可以使用一些新的语法。</p> <p>对于有可选参数的函数,我们并不清楚这个参数是否可选。有了ES6,我们能够提供一个默认值让这个变得明显:</p> <pre> <code class="language-javascript">function something(a, b = 'default value') { //if b is not passed, its value becomes 'default value' }</code></pre> <p>最佳实践:给可选参数提供默认值</p> <p>我们可以使用解构参数列表中对象和它的默认值。</p> <pre> <code class="language-javascript">function foo(required, { optionalA, optionalB } = { }) { //available variables: //required, optionalA, optionalB } foo('hi', { optionalA: 1, optionalB: 1337 });</code></pre> <p>这给了你两全其美的办法。你可以方便地使用对象作为参数,但是对象的属性能够从函数的注释中看到。</p> <p>最佳实践:使用ES6解构重要的地方</p> <h3>总结</h3> <p>对于上述建议的补充,在函数声明前使用注释是另一个有用的习惯。这对于读者来说非常有用,能够迅速了解大概,不仅仅是函数的参数,还有他们的类型和其他注意点。</p> <p>总结:</p> <ul> <li> <p>使用单独的命名参数</p> </li> <li> <p>把可选参数放在最后</p> </li> <li> <p>对于多个可选参数适用对象</p> </li> <li> <p>默认值可以用来表明可选参数</p> </li> <li> <p>使用解构来说明对象参数</p> </li> </ul> <p>这是另一个你可以用ES6默认参数做的有趣事情。通常情况下,如果你不传递一个必要的参数,什么事都不会发生。但是有了默认值,我们可以让代码自动抛出一个缺少必要参数的错误!David Walsh有一个 <a href="/misc/goto?guid=4959730203282033887" rel="nofollow,noindex">对此的极佳总结</a> 。</p> <p> </p> <p>来自:http://www.zcfy.cc/article/best-practices-for-javascript-function-parameters-codeutopia-2053.html</p> <p> </p>