函数变量signature/arguments
Function variable signature/arguments
我有一个带有可变参数的函数,类似于
function fn(...args) {
let str, arr, obj;
if (args.length == 1) {
if (typeof args[0] == 'object') {
obj = args[0];
} else {
str = args[0];
}
} else if (args.length == 2) {
str = args[0];
if (typeof args[1] == 'object') {
obj = args[1];
} else {
arr = args[1];
}
} else if (args.length == 3) {
[str, arr, obj] = args;
}
}
而 API 是
fn()
fn(String str)
fn(Object obj)
fn(String str, Array arr)
fn(String str, Object obj)
fn(String str, Array arr, Object obj)
它有意放宽类型(例如,某些参数可能未定义)。
是浏览器代码,比较紧凑。这种方式当然可行,但是否有更好的方法、更简洁且更易于维护?任何 Node 或通用 JS 库都能够在占用空间和依赖性方面保持适度的同时完成肮脏的工作?
"problem" 我看到的是,您不仅重载了可变参数,而且还重载了参数 types。这种组合导致了一个混乱的实现,只会在很长的 运行.
中伤害你
这是一种使用辅助函数的不同编写方式,但您仍然处于痛苦的世界中(更多内容见下文)。
function fn(...args) {
function aux(str, arr, obj) {
// this function will always have str, arr, and obj
}
// Warning: this has an error anyway because (typeof []) is also 'object'
switch (args.length) {
case 1: return typeof args[0] === 'object'
? aux(null, null, args[0])
: aux(args[0], null, null);
case 2: return typeof args[0] === 'object'
? aux(args[0], null, args[1])
: aux(args[0], args[1], null);
case 3: return aux(args[0], args[1], args[2]);
}
}
通过上述实现,您可以使用 5 种独特的方式来调用您的函数,所有这些方式都旨在被接受和适当。
缺点
- 难以记忆API - 根据哪些参数我会得到哪个结果?当我传递一个字符串和一个对象时,我先传递哪个?等等
- 重构噩梦 - 如果功能需要更改,您需要支持所有 5 种调用。一旦您通过一个函数强制完成所有 5 种行为 api,就无法在不破坏针对此函数编写的现有代码的情况下分离行为。
- 函数定义中异常复杂的样板 - 大多数函数只是将参数映射到它们的局部参数,而这一切都由 JavaScript 本身为您处理。你的函数现在有一堆代码改变了 JavaScript 的行为方式,你的代码可读性因此受到影响。对于您使用这种 "design".
编写的每个函数,此样板将成倍增加
- 难以检测的类型 -
typeof []
将 return 'object'
而不是您可能想的“array
”。您将不得不编写大量极端情况以确保您正确检测所有类型。 JavaScript 不是一种类型化语言,因此尝试基于 typeof
协商行为作为您的首选检测机制将导致各种令人头疼的问题。所有这些额外的代码意味着出现错误的可能性更大,需要维护的代码更多,并且软件的整体质量最终会受到影响。
优点
- 此部分有意留空
开发人员经常犯这样的错误,因为一种语言允许某种思维方式,无论他们想出什么代码,只要它compiles/executes,那没关系。
这是一个非常大的误解,通常为什么有经验的开发人员 appreciate/favour 一种语言更严格,限制更多。
总之,祝你好运。
我有一个带有可变参数的函数,类似于
function fn(...args) {
let str, arr, obj;
if (args.length == 1) {
if (typeof args[0] == 'object') {
obj = args[0];
} else {
str = args[0];
}
} else if (args.length == 2) {
str = args[0];
if (typeof args[1] == 'object') {
obj = args[1];
} else {
arr = args[1];
}
} else if (args.length == 3) {
[str, arr, obj] = args;
}
}
而 API 是
fn()
fn(String str)
fn(Object obj)
fn(String str, Array arr)
fn(String str, Object obj)
fn(String str, Array arr, Object obj)
它有意放宽类型(例如,某些参数可能未定义)。
是浏览器代码,比较紧凑。这种方式当然可行,但是否有更好的方法、更简洁且更易于维护?任何 Node 或通用 JS 库都能够在占用空间和依赖性方面保持适度的同时完成肮脏的工作?
"problem" 我看到的是,您不仅重载了可变参数,而且还重载了参数 types。这种组合导致了一个混乱的实现,只会在很长的 运行.
中伤害你这是一种使用辅助函数的不同编写方式,但您仍然处于痛苦的世界中(更多内容见下文)。
function fn(...args) {
function aux(str, arr, obj) {
// this function will always have str, arr, and obj
}
// Warning: this has an error anyway because (typeof []) is also 'object'
switch (args.length) {
case 1: return typeof args[0] === 'object'
? aux(null, null, args[0])
: aux(args[0], null, null);
case 2: return typeof args[0] === 'object'
? aux(args[0], null, args[1])
: aux(args[0], args[1], null);
case 3: return aux(args[0], args[1], args[2]);
}
}
通过上述实现,您可以使用 5 种独特的方式来调用您的函数,所有这些方式都旨在被接受和适当。
缺点
- 难以记忆API - 根据哪些参数我会得到哪个结果?当我传递一个字符串和一个对象时,我先传递哪个?等等
- 重构噩梦 - 如果功能需要更改,您需要支持所有 5 种调用。一旦您通过一个函数强制完成所有 5 种行为 api,就无法在不破坏针对此函数编写的现有代码的情况下分离行为。
- 函数定义中异常复杂的样板 - 大多数函数只是将参数映射到它们的局部参数,而这一切都由 JavaScript 本身为您处理。你的函数现在有一堆代码改变了 JavaScript 的行为方式,你的代码可读性因此受到影响。对于您使用这种 "design". 编写的每个函数,此样板将成倍增加
- 难以检测的类型 -
typeof []
将 return'object'
而不是您可能想的“array
”。您将不得不编写大量极端情况以确保您正确检测所有类型。 JavaScript 不是一种类型化语言,因此尝试基于typeof
协商行为作为您的首选检测机制将导致各种令人头疼的问题。所有这些额外的代码意味着出现错误的可能性更大,需要维护的代码更多,并且软件的整体质量最终会受到影响。
优点
- 此部分有意留空
开发人员经常犯这样的错误,因为一种语言允许某种思维方式,无论他们想出什么代码,只要它compiles/executes,那没关系。
这是一个非常大的误解,通常为什么有经验的开发人员 appreciate/favour 一种语言更严格,限制更多。
总之,祝你好运。