JavaScript 中的第一个可选参数
Optional argument first in JavaScript
为了方便用户,我有一个函数,它首先接收一个可选参数,然后接收所需的参数。例如:
ns.myFunction('optional arg', function(){
//the required callback
});
我这样做而不是执行以下操作,因为回调正文可能很长,并且用户可能会忘记覆盖可选参数的默认值:
ns.myFunction(function(){
//the required callback
}, 'optional arg');
目前我这样做是为了检查:
function myFunction(first, second) {
//if second is undefined and first is a function
if (typeof second === 'undefined' && typeof first === 'function') {
second = first;
}
}
问题
- 这是正确的方法吗?
- 我将如何做到这一点以使其缩放,特别是如果所需参数之前有 N 个可选参数?
这不是正确的方法,因为按照惯例,可选参数始终放在末尾。你会看到一个原因:处理它们要容易得多。如果您关心匿名函数的长度,则 API 的客户端应使用函数引用或变量:
function callback1() { //...
var callback2 = function() {//...
myFunction(callbackX, optional);
逃逸this
的问题可以用bind()
来解决。
如果你真的想走多个可选参数和最后回调的路径,我可以想到两种方法:arguments
对象或将所有可选参数包装在一个options
对象中。
使用arguments
您可以编写:
var lastOptionalIndex = arguments.length - 2;
var callback = arguments[lastOptionalIndex + 1]; //required callback is always last
var optionalFirst = lastOptionalIndex >=0? arguments[0] : undefined;
var optionalSecond = lastOptionalIndex >=1? arguments[1] : undefined;
//...
看看它与以下相比有多丑陋:
function myFunction(callback, firstOptional, secondOptional //...
对于options
包装器对象,您始终有两个参数:
function myFunction(options, callback);
其中options
只是一个对象:
{
firstOptional: 1,
secondOptional: 'foo'
//...
}
它可以很容易地用ArgueJS完成:
function myFunction (){
arguments = __({first: [String], second: Function})
// and now on, you can access your arguments by
// arguments.first and arguments.second
}
一个非常相似的例子可以在ArgueJS的第一个例子中找到。请注意,只有中间的参数是必需的:
function range(){
arguments = __({start: [Number, 0], stop: Number, step: [Number, 1]})
for(var i = arguments.start; i < arguments.stop; i += arguments.step)
console.log(i);
}
代表:
>>> range(3)
0
1
2
>>> range(3, 5)
3
4
>>> range(0, 5, 2)
0
2
4
您可以根据函数参数的数量配置函数参数:
myFunction() {
let first, second;
if (arguments.length === 2) {
[first, second] = arguments;
} else if (arguments.length === 1) {
[second] = arguments;
}
if ( ! first) {
// first is undefined, so only second argument was passed.
}
}
ES6 解构使代码干净且适合扩展。
命名任何参数。 你可以简单地说:
if (arguments.length < 2) // There are no optional parameters
并通过参数[i]检索每个参数。该函数位于 arguments[arguments.length - 1]。
在次要说明中,typeof 运算符总是返回一个字符串,因此可以使用 == 代替 ===
争论JS:
function range(){
arguments = __({start: [Number, 0], stop: Number, step: [Number, 1]});
for(var i = arguments.start; i < arguments.stop; i += arguments.step)
console.log(i);
}
使用 ES6 变得更漂亮:
function range(){
{start, stop, step} = __({start: [Number, 0], stop: Number, step: [Number, 1]})
for(var i = start; i < stop; i += step)
console.log(i);
}
或咖啡脚本:
range = ->
{start, stop, step} = __ {start: [Number, 0], stop: Number, step: [Number, 1]}
console.log i for i in [start...stop] by step
如果你真的想先传递多个可选参数,你可以这样做:
function myFunction() {
alert("optional:");
for(var i=0; i<arguments.length-1) alert(arguments[i]);
alert("function: "+ arguments[arguments.length-1]);
}
但它相当丑陋。我认为你应该把可选的东西放在最后。
function test(num = 1) {
console.log(typeof num)
}
test() // 'number' (num is set to 1)
test(undefined) // 'number' (num is set to 1 too)
// test with other falsy values:
test('') // 'string' (num is set to '')
test(null) // 'object' (num is set to null)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters
一个简单的函数方法:
想法:
- 编写一个函数myFunction(必需,可选),其中可选参数是最后一个,因此很容易来处理。
- 使用函数 appendFirstArgumentIf() 从 myFunction 创建一个新函数 myNewFunction(可选,必需)。
- 函数 appendFirstArgumentIf 调用 myFunction,如果它传递测试函数,则第一个参数移动到最后一个位置,否则它不会更改参数。
_
/**
* @param {function} fn(a,...b)
* @param {function} argumentTest - a function to test the first parameter
* @return {function} returns a function that passes its first argument into
argumentTest. If argumentTest returns true, fn is called with the first
argument shifted to the last position else fn is called with the arguments
order unchanged
*/
function appendFirstArgumentIf (fn,argumentTest){
return function(a,...b){
return argumentTest(a) ? fn(...b,a) : fn(a,...b)
}
}
用法:
function myFunction(callback, string){
string = string ? string : 'Default Message'
callback(string)
}
var myNewFunction = appendFirstArgumentIf(myFunction,
firstArgument=> typeof firstArgument !== 'function')
myNewFunction('New Message', console.log) // using console.log as callback function
//>>>New Message
myNewFunction(console.log)
//>>>Default Message
也可以这样做:
function mySecondFunction(callback, name, string){
string = string ? string : 'Welcome'
callback(string, name)
}
var myLatestFunction = appendFirstArgumentIf(mySecondFunction,
firstArgument=> typeof firstArgument !== 'function')
myLatestFunction('Hello', console.log, 'John')
//>>>Hello John
myLatestFunction(console.log, 'John')
//>>>Welcome John
- 而循环只设置php中输入字段中的第一个值
- 错误:$injector:modulerr模块错误(我的第一个SPA应用程序)
- IE11中的第二个调用取消了第一个Fetch API调用
- Javascript XMLHttpRequest——只有第一个POST请求有效
- 使用javascript或angularjs特定过滤器搜索字符串中第一个img标记的json值
- 将OnClick函数设置为<ul>,最后一个ul是擦除第一个ul-s
- RxJS油门行为;立即获取第一个值
- Angular UI网格:如何通过第一个UI网格中的按钮使第二个UI网格可见
- 选择多个实例中的第一个
- 如何在调用下一个请求之前完成第一个Ajax Get请求
- 用javascript将参数从一个函数传递到另一个函数
- Lodash:返回对象的第一个键,该对象的值(即数组)中有一个给定的元素(即字符串)
- 看起来第一个console.log是'It’不太对
- 与杜兰达尔合作的第一个JavaScript项目.尝试从第三方 API 获取数据
- 节点发布错误对象的第一个“属性”
- 如果在第一个 jsp 页面设置了刷新参数,则会刷新所有 jsp 页面
- 使用 Function.prototype.bind.apply(Obj, args) 将参数传递给对象,只传递第一个元
- 提取第一个url参数,然后将其放入脚本标记中
- 第一个next()调用的参数所在的位置
- 逗号操作符返回参数列表中的第一个值,而不是第二个值