Method Finder for JavaScript

文字列を結合するメソッドがJavaScriptに存在することは分かっているのに、そのメソッドの名前が思い出せず、リファレンスを一々参照することはありませんか?

そんな時に便利なMethod Finderを作ってみました。オブジェクト・返り値・引数を与えると、Method Finderはそれらの条件を満たすメソッド名を返します。元々はSmallTalkにあった機能のようです。私もJavaScriptのメソッド名をよく忘れるので、Method FinderのJavaScript版を作ってみました。下記のサイトより試せます。

Method Finder for JavaScript

実装にはAndrew Birkett's MethodFinder in Rubyを参考にしました。

メインのコードはこんな感じです。あまり格好よくありません。

追記:id:brazilさんよりトラックバックを頂きました。
http://d.hatena.ne.jp/brazil/20060521/1148223479

(cloneのとこ..、破壊的なメソッドを呼んでも大丈夫なのかな..)

破壊的なメソッドを呼んでもある程度大丈夫なように修正しました。また、配列の同値判定処理を加えました。とはいえ、まだバグがありそうな気がします。Rubyならここまで苦労しないのですが・・。

Object.clone = function(object){
    if(object.constructor == Array){
	return object.concat();
    } else if(object.concat == Date){
	return new Date(object);
    } else if(object.concat == RegExp){
	return new RegExp(object);
    } else if(object.concat == Object){
	var copyto = {};
	for(var prop in to){
	    copyto[prop] = Object.clone(object[prop])
	};
	return copyto;
    } else {
	return object;
    }
}

Object.equal = function(from, to){
    if(from.constructor != to.constructor){
	return false;
    }
    if(from.constructor == Array){
	if(from.length != to.length){
	    return false;
	}
	for(var i = 0; i < from.length; i++){
	    if(!Object.equal(from[i], to[i])){
		return false;
	    }
	}
	return true;
    } else if(from.constructor == Object){
	for(var property in from){
	    if(!Object.equal(from[property], to[property])){
		return false;
	    }
	}
	return true;
    } else {
	return from == to;
    }
}

var MethodFinder = {
    find: function(object, expectedResult, arg){
	var foundNames = [];
	var properties = this.methodNames.concat();
	for(var property in object){
	    properties.push(property);
	}
	
	for(var i = 0; i < properties.length; i++){
	    var name = properties[i];
	    if(typeof(object[name]) == 'function'){
		try{
		    if(Object.equal(object[name].apply(Object.clone(object), arg),
				    expectedResult)){
			foundNames.push(name);
		    }
		}catch(e){
		    
		}
	    }
	}
	return foundNames;
    },
    methodNames: 
    [
     "parse", "UTC",
     "eval", "isFinite", "isNaN", "parseFloat", "parseInt",
     "decodeURI", "decodeURIComponent", "encodeURI", "encodeURIComponent",
     "abs", "acos", "asin", "atan", "atan2", "ceil", "cos", "exp", "floor",
     "log", "max", "min", "pow", "random", "round", "sin", "sqrt", "tan",
     "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable",
     "toLocaleString", "toString", "valueOf",
     "apply", "call",
     "concat", "join", "pop", "push", "reverse", "shift", "slice", "sort",
     "splice", "unshift",
     "charAt", "charCodeAt", "fromCharCode", "indexOf", "lastIndexOf",
     "localeCompare", "match", "replace", "search", "split", "substring",
     "toLocaleLowerCase", "toLocaleUpperCase", "toLowerCase",
     "toUpperCase",
     "toExponential", "toFixed", "toPrecision",
     "getDate", "getDay", "getFullYear", "getHours", "getMilliseconds",
     "getMinutes", "getMonth", "getSeconds", "getTime",
     "getTimezoneOffset", "getUTCDate", "getUTCDay", "getUTCFullYear",
     "getUTCHours", "getUTCMilliseconds", "getUTCMinutes", "getUTCMonth",
     "getUTCSeconds", "setDate", "setFullYear", "setHours",
     "setMilliseconds", "setMinutes", "setMonth", "setSeconds", "setTime",
     "setUTCDate", "setUTCFullYear", "setUTCHours", "setUTCMilliseconds",
     "setUTCMinutes", "setUTCMonth", "setUTCSeconds", "toDateString",
     "toLocaleDateString", "toLocaleString", "toLocaleTimeString",
     "toTimeString", "toUTCString",
     "exec", "test"
     ]
}