uncurryThis 関数

にて大変有用な書き方を身に着けた。
Function.prototype.bindFunction.prototype.callの黒魔術的なもの。

obj.hasOwnProperty("prop");

と書くところをcallで書くと

var func = Object.prototype.hasOwnProperty;
func.call(obj, "prop");

と書ける。さらにcallをbindしてみると

var func2 = func.call.bind(func);
func2(obj, "prop");

となる。さらに、bindをbindすると

var func3 = func.bind.bind(func.call)(func);
func3(obj, "prop");

ここで、func.bindや、func.callはbindで束縛されるので、Function.prototype.bindFunction.prototype.call(===Function.prototype.bind.call)と同じになるので。

var bind = Function.prototype.bind;
var func4 = bind.bind(bind.call)(func);

となる。

var bind = Function.prototype.bind,
    uncurryThis = bind.bind(bind.call);

var hasOwn = uncurryThis(Object.prototype.hasOwnProperty);

var obj = Object.create(null);
obj.foo = "FOO";

hasOwn(obj, "foo"); // true

と、束縛したいオブジェクトを第一引数にして実行できるようになる。
上記、hasOwnPropertyの例では、オブジェクトがObjectを継承していないことを恐れて、Object.prototype.hasOwnProperty.call(obj, "foo")などとやらなくても簡単に書けるようになるわけだ。

これができると、Mozilla JavaScript 1.6 の機能であるArray および String の汎用化のようなものを簡単に定義できる。


function f1 () {
  Array.slice(arguments).forEach(function(arg){
    // ...
  });
}
function f2 () {
  return Array.map(arguments, function(str){ return str.toUpperCase(); })
}

などなど、Mozilla JavaScriptでは普通に出来ていたことが、他のエンジンでもできるようになる。
便利ー。