Function.prototype.bindを名前付き引数に対応させる
使えるかどうか分からないけど。
ネイティブメソッドは引数名が取得できないので名前付き引数のbindの有難みが無い…orz
/* bindAny(thisObj[, args][, namedArgs]) * bindAny(thisObj[, namedArgs][, args]) // Syntax sugar */ Function.prototype.bindAny = function(thisObj) { var orig = this; var boundArgs, boundNamedArgs; if (Array.isArray(arguments[1])) { boundArgs = arguments[1]; boundNamedArgs = arguments[2]; } else { boundNamedArgs = arguments[1]; boundArgs = arguments[2]; } if (!boundArgs) boundArgs = []; if (!boundNamedArgs) boundNamedArgs = {}; /* build pre arguments * * 元の関数の引数名の列を取得 * nameに対応する位置にnamedArgs[name]を入れる */ var argNames = orig.toString() .match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(/\s*,\s*/); var args = []; for (var i = 0, l = argNames.length; i < l; ++i) { var name = argNames[i]; if (boundNamedArgs.hasOwnProperty(name)) { args[i] = boundNamedArgs[name]; } } var slice = Array.prototype.slice, news = []; function bound() { /* build actual arguments * * pre-argumentsの先頭から順にundefinedにargsを入れる * 残ったargsは末尾に追加 */ var ta = boundArgs.concat(slice.call(arguments)); var a = slice.call(args); for (var i = 0, l = a.length; 1 <= ta.length && i < l; ++i) { if (typeof a[i] === 'undefined') a[i] = ta.shift(); } if (ta.length >= 1) a = a.concat(ta); if (this instanceof bound) { /* I am a constructor! */ if (!news[l]) { var as = []; for (var i = 0, l = a.length; i < l; ++i) as.push('a[' + i + ']'); var evs = 'news[l]=function(){return new orig(' + as.join(',') + ');};'; eval(evs); } var ret = news[l](); if (typeof ret.__proto__ === 'object') { ret.__proto__ = bound.prototype; } return ret; } else { return orig.apply(thisObj, a); } } function fnop() {} fnop.prototype = orig.prototype; bound.prototype = new fnop(); return bound; };
動作確認
function f(a, b, c, d) { console.log(arguments); } f.bindAny(null, [1, 2], {c: 3, d: 4})(); // f(1, 2, 3, 4) f.bindAny(null, [1, 2])(); // f(1, 2) f.bindAny(null, [1, 2])(3, 4); // f(1, 2, 3, 4) f.bindAny(null, {c: 3, d: 4})(1, 2); // f(1, 2, 3, 4) f.bindAny(null, {c: 3, d: 4})(); // f(undefined, undefined, 3, 4) f.bindAny(null, {c: 3})(1, 2, 4); // f(1, 2, 3, 4)
参考