JavaScript没有关键字参数的真实概念,同时对于传递给函数的内容非常灵活。 因此,很容易混淆或打结关于以什么顺序传递给函数的内容。 我发现它更好,为了我自己的理智,以及使用我的代码的其他人,总是只将一个名为params的参数传递给我的函数,并将所有内容嵌入其中。
在我试图说服你这个是个好主意之前,让我们看一下参数处理在JavaScript中是如何工作的。
函数可以在其声明中指定任意数量的参数:
当你使用正确数量的位置参数调用此函数时,一切都有意义:
在许多其他语言中,做任何不同的事情都会导致异常。 不提供足够的论据? 提供太多论点? 在JavaScript中不是这样。
尝试使用较少的参数调用上面的函数:
或者有太多:
发生的事情是,JavaScript并没有真正具有与你在OO语言中找到的方法“签名”相同的概念。当你在函数声明中声明一个参数名称时,你所做的就是在该函数内部使用它时为该位置参数附加一个标签。如果未传入该参数,则标签未定义。如果你传入一个没有位置标签的参数,那么它仍然在函数范围内,你只是没有它的名字。
这解释了上面函数调用的输出。当我们省略c的值时,c未定义,+ b + c导致NaN。当我们传入第四个参数时,函数只是继续进行,好像它不存在一样。
那么能够传递没有标签的值的重点是什么,因此无法在函数内部访问?那么,该陈述的后半部分并非如此。我们可以访问该值,如果你知道在哪里看,那就是在所有声明的函数中存在的特殊参数局部变量。它是一个特殊的野兽,有自己的类型,如果我们喜欢,我们可以将它转换为数组:
(注意我在这里使用的是ES5,它肯定会在你选择的浏览器中运行。在ES6中使用Array.from(arguments)有一种稍微快一点的方法)。
我们已经宣布这个函数没有位置参数,只是为了使这一点非常明确。 我们现在可以用任意数量的参数调用它,它会反映给我们:
从ES6开始,你需要了解的有关参数的另一件事是,你可以像这样设置默认值:
但是你不能将参数作为关键字传递。 我的意思是,以下内容并不像你期望的那样有效:
最终,这意味着函数声明的参数只不过是函数的功能指南。 结合缺少真正的关键字参数,因此很难理解函数声明及其文档,并确保你传递正确的内容。
看到类似于以下内容的JavaScript文档并不罕见:
function doIt(oneThingOrAnother,[someOption。[someOtherOption]])
使用OneThing或AnotherThing作为第一个参数调用此函数,然后你的选项是......
对我来说,这种函数声明很尴尬,在我看到它的工作原理之前,几乎总会导致一些试验结束错误。
相反,我更喜欢使用单个函数参数params,记录其结构,而不必担心变量参数列表。 我们可以像这样快速重写上面的函数:
那还不完美,我们会随着时间的推移清理它......
让我们深入探讨为什么这种方法是一个好主意:
它摆脱了参数的位置排序 - 你的用户不再需要反复提醒自己哪些顺序传递参数。 当我调用此函数时,我可以以任何方式执行此操作:
它允许我连贯地传递可变数量的参数 - 我可以省略一个参数,而不会弄乱排序或行为。 就像我只想传递一个或另一个:
作为一个函数作者,如果调用者没有指定参数,它可以很容易地默认参数:
(注意我们不使用旧式的var oneThing = params.oneThing ||“defaultOneThing”方法,因为这最终会破坏你的功能)
这也意味着我可以使用命名良好的参数来宣传我的函数的功能,而不必坚持函数内的那些参数名称。 这可能是一个非常方便的区别。 例如:
在文档方面,函数调用本身变得相当自我说明,或者至少更容易理解:
与:
在函数声明方面,很容易记录params对象的内部,JSDoc可以很好地为你列出该文档。 这是最近项目的文档片段,以及它生成的JSDoc输出:
以这种方式声明你的功能有很多充分的理由。 当然,与JavaScript一样,它是一种惯例,你可能会发现想要违反它的情况。 你当然必须使用其他人的代码,这种代码不会这样。 我向你保证,从长远来看,编写你自己的代码就可以避免因为使用声明糟糕的函数而导致的低级别问题。
领取专属 10元无门槛券
私享最新 技术干货