Titanium Mobile でRPG開発進捗48日目

先日id:dataichxさんにご指摘頂いたcloneについて
ようやく手をつけることが出来ました。


まず、教えて頂いたurlを参考に、よさそうな感じのソースをコピー。
参考
http://blogs.msdn.com/b/ie/archive/2010/10/27/ecmascript-5-part-1-reusable-code.aspx


問題発生。以下の2点。

  • ECMAScript5に対応した環境じゃないと使えないメソッドがあった
  • Object.prototypeにcloneを追加すると怒られる


仕方が無いので、原始的にコピーを行うclone関数を作成することに。
階層や配列の扱いにも対応してみた。
以下がソースです。
※ 2011/11/04 @rlldiさんのアドバイスを元に変更しています。

var clone = function (o) {
	if (typeof o != 'object') return o;
//	if (o.hasOwnProperty('length')) {
//	if(Object.prototype.toString.call(o) === "[object Array]") {
/*
	if (o instanceof Array) {
		var n = [];
	} else {
		var n = {};
	}
*/
	var n = (o instanceof Array)?[]:{};
	for (var p in o) {
		n[p] = clone(o[p]);
	}
	return n;
};


typeofでobject以外の場合は値として戻す。
lengthメソッドがあるか確認して、あれば配列として宣言
なければオブジェクトとして宣言することにした。
こうしないと配列もオブジェクトになってしまって
lengthが取得できなくなるのだ。


これがはたして正しいのかはわからんけれども
正常に動いているので今のところよしとしています。
問題点や、その問題点に関する解決方法があったらご指摘ください。


まぁ、自分が利用する範囲では問題ないので
利用範囲を限定すれば問題ないとは思います。

追記 2011/11/4


[twitter:@rlldi]さんからTwitterでアドバイスを貰いました。
insetanceof演算子しらなかったのでありがたかったです。
そこでこんなソースになりました。

//	if (o.hasOwnProperty('length')) {
	if (o instanceof Array) {


動きました!ばんじゃーい!
でも、instanceof演算子をぐぐったところ次の記事に行き当たりました。


Array かどうかを判定するいくつかの方法について - latest log
http://d.hatena.ne.jp/uupaa/20090116/1232051707


記事は結構古いものなのですが、jQueryのinArrayがどういう実装なのか
というところが速度を含めた形で書いてあります。
遅くなるけど、せっかくなので動作検証してみました。

//	if (o.hasOwnProperty('length')) {
//	if (o instanceof Array) {
	if (Object.prototype.toString.call(o) === "[object Array]") {


動きました!ばんじゃーい!
でも、まぁ文字列操作なんで遅いんでしょうね。
で、判定は結局 if (o instanceof Array) { で行けそうです。
ただ、typeofみたいに型名は取れませんので、型名取ろうかっていう話。


JavaScript メモ by kanegon
http://www2.wbs.ne.jp/~kanegon/doc/jsmemo.txt


2003年の記事でした。
でも気になって実行してみました。

var typename = function (o) {
	if (typeof(o) == "object") {
		if ((""+o.constructor).match(/^\s*function +(\w+)/)) return RegExp.$1;
	}
	return typeof(o);
};


オブジェクト名取れた!ばんじゃーい!
ということで、cloneの中身を少しだけ変えました。