◆ 無駄な努力

いきなりですが Rっぽく引数渡したいなーってことありませんか?

R がどういうのかというと
x <- read.table("data.txt", header=T, skip=1)
こういうの
<- は代入ですがそこはどうでもいいところです

引数を渡すところで = を使ってます
data.txt は第一引数に引数を渡していて header や skip は何番目の引数かはわからないですが header や skip という名前の引数に値を渡せています

気軽に引数の名前を変えられない欠点もありますが 何番目という情報よりこの値が何なのかがわかったほうがコードがわかりやすいですし 引数の3番目を省略して4番目を書きたいというときなどに便利です

JavaScript でもこれがやりたいですが 言語としてサポートされてませんし今後の Ecma Script でも予定はなさそうです
なので 近いことをやろうとなんかいろいろやってみます

JavaScript でやるとどうなるか

当たり前だと思いますが JavaScript でやると思い通りに動きません
var f = function(param1, param2, param3, param4){
console.log("param1 : ", param1)
console.log("param2 : ", param2)
console.log("param3 : ", param3)
console.log("param4 : ", param4)
}
var a = 1, b = "abc"
f(a, 10, param4 = false, param3 = b)
param1 : 1
param2 : 10
param3 : false
param4 : "abc
param4 = false などは関数を呼び出す前に評価されてしまうので スコープに param4 がなければ param4 というグローバル変数が作られて false が代入されます

関数呼び出すときは これと一緒になってます
f(1, 10, false, "abc")
受け取る側は単純にこの順番で受け取ります

オブジェクトにして 評価させない

= と書いてもダメなのは言語仕様なのでどうしようもないです
なのでオブジェクトにしてみます
var x = "x", y = "y", z = "z"

f(x,y, {param4:false}, {param3:z})

function f(param1, param2, param3, param4){
// 引数処理
[].slice.call(arguments).map(function(e){
if(e instanceof Object){
var key = Object.keys(e).pop()
"param1" === key && (param1 = e[key])
"param2" === key && (param2 = e[key])
"param3" === key && (param3 = e[key])
"param4" === key && (param4 = e[key])
}
})

// ここから本体
console.log("param1 : ", param1)
console.log("param2 : ", param2)
console.log("param3 : ", param3)
console.log("param4 : ", param4)
}
param1 : x
param2 : y
param3 : z
param4 : false
できています
が 引数処理を全関数に書きたくないですし  x などの普通に順番通りに渡したい変数がオブジェクトだったら困ります

引数名で渡す場合に関数を通す

まず オブジェクトを引数で渡したい時の対処をします

特定の関数を通して引数を渡すようにします
この関数では特定のキーをオブジェクトに追加するだけです
絶対に他で使わないキー名にします
引数を受け取る側では そのキーがあれば引数名を指定して引数が渡された と判断して処理します
var x = "x", y = {val:"y"}, z = "z"
f(x,y, w({param4:-100}), w({param6:z}), w({param3:false}))
function w(obj, decode){
if(decode){
if(obj.fixed_key === "fixed_value"){
// 固定キーと固定値あればkeyとvalueで返す
delete obj.fixed_key
var k = Object.keys(obj).pop()
var v = obj[k]
obj = {
key: k,
value: v,
}
}else{
obj = false
}
}else{
// 固定キーと固定値をセット
obj.fixed_key = "fixed_value";
}
return obj;
}
function f(param1, param2, param3, param4){
// 引数処理
[].slice.call(arguments).map(function(e){
var t = w(e, true)
if(t){
var key = t.key
"param1" === key && (param1 = t.value)
"param2" === key && (param2 = t.value)
"param3" === key && (param3 = t.value)
"param4" === key && (param4 = t.value)
}
})

// ここから本体
console.log("param1 : ", param1)
console.log("param2 : ", param2)
console.log("param3 : ", param3)
console.log("param4 : ", param4)
}
param1 : x
param2 : Object {val: "y"}
param3 : false
param4 : -100

長いですねー
w 関数のところは一度だけ書いておけばいいのでまぁいいとしましょう


キーを追加するのは 特別なオブジェクトでラップして そのオブジェクトのインスタンスかどうかで判断するとかでもよさそうです
こんなの
function w(obj, decode){
if(decode){
return obj instanceof ww ? obj.arg : false
}else{
return new ww(obj)
}
}
function ww(arg){
var k = Object.keys(arg).pop()
var v = arg[k]
this.arg = {key:k, value:v}
}
ちょっとシンプルになります

最初から全部オブジェクトにする?

最初から全部をひとつのオブジェクトで渡せば上の w のような関数はいらないんじゃないかと思いました
f({
param1: "a" ,
param4: false
})
function f(args){
var param1, param2, param3, param4
// 引数処理
for(var key in args){
"param1" === key && (param1 = args[key])
"param2" === key && (param2 = args[key])
"param3" === key && (param3 = args[key])
"param4" === key && (param4 = args[key])
}

// ここから本体
console.log("param1 : ", param1)
console.log("param2 : ", param2)
console.log("param3 : ", param3)
console.log("param4 : ", param4)
}
param1 : a
param2 : undefined
param3 : undefined
param4 : false
シンプルになりました
ありといえばありですが key を書きたくなくて単純に順番に渡したいだけだと手間が増えてしまいます

key 無しも可能に

「全部で 1 つのオブジェクト」 を改良?して単純な並びだけでの受け取りもできるようにしてみました
f([10, "xyz"], {
param4: -100,
})
function f(stdargs, exargs){
var param1, param2, param3, param4
// 引数処理
stdargs.forEach(function(e, i){
i === 0 && (param1 = e)
i === 1 && (param2 = e)
i === 2 && (param3 = e)
i === 3 && (param4 = e)
})
for(var key in exargs){
"param1" === key && (param1 = exargs[key])
"param2" === key && (param2 = exargs[key])
"param3" === key && (param3 = exargs[key])
"param4" === key && (param4 = exargs[key])
}

// ここから本体
console.log("param1 : ", param1)
console.log("param2 : ", param2)
console.log("param3 : ", param3)
console.log("param4 : ", param4)
}
param1 : 10
param2 : xyz
param3 : undefined
param4 : -100
第一引数に配列で通常の引数を渡すように受け取り側の順番で書きます
第ニ引数に引数名をキーにしたオブジェクト形式で書きます

それなりに良さそうです
受け取り側の引数処理を除けば

引数受け取り側を短く

受け取り側をもっと短くしたいですが 引数の名前が何番目になるのか外側からわからない以上 関数の最初に eval を使って同じことをさせるくらいしかできなそうです

ECMA6 の分割代入を使えれば短く書くことが出来ます
eval 使うのに比べると この方法が良いのかもしれません
Chrome はまだ動かないですけど Firefox なら動きます
// これを用意しておく
function agg_arg(arg_names, arr, obj){
var ret = {}
arg_names.forEach(function(e, i){
ret[e] = e in obj ? obj[e] : arr[i]
})
return ret
}

function f(stdarg, exarg){
// 関数の最初にこれを書く
var {param1, param2, param3, param4} =
agg_arg(["param1", "param2", "param3", "param4"], stdarg, exarg)

// ここから本体
console.log("param1 : ", param1)
console.log("param2 : ", param2)
console.log("param3 : ", param3)
console.log("param4 : ", param4)
}

まとめ

まとめると 変なことしないで普通に引数は順番にかけばいいと思います