カテゴリ: 4

Javascriptでオブジェクトのディープコピー

参照型

Javascriptでオブジェクトをコピーということは基本的にできないみたい。Javascriptにおけるオブジェクトというのは、DOM要素と配列({} と [])などはオブジェクトとして扱われ、 1 とか “1” は 数値と文字列として扱われる。

<span class="synIdentifier">var</span> a = <span class="synIdentifier">[</span>1, 2, 3 <span class="synIdentifier">]</span>;
<span class="synIdentifier">var</span> b = a;
b<span class="synIdentifier">[</span>0<span class="synIdentifier">]</span> = 100;
<span class="synStatement">alert</span>(a);
Code language: JavaScript (javascript)

こうすると、bの変数の配列を一番目を変更したのにも関わらずaの配列の値が変わってる。これは変数aと変数bに格納されているデータを「参照」しているアドレスが同じ場所になってしまっているからなんだそうです。これを参照渡しと言って、Javascriptではどうあがいてもオブジェクトは参照渡しになってしまう。

ただ、DOM要素や関数が配列内に含まれていなければある方法でオブジェクトをディープコピーできる。

JSON

<span class="synIdentifier">var</span> a = <span class="synIdentifier">[</span>1, 2, 3 <span class="synIdentifier">]</span>;
<span class="synIdentifier">var</span> b = JSON.parse(JSON.stringify(a));
b<span class="synIdentifier">[</span>0<span class="synIdentifier">]</span> = 100;
<span class="synStatement">alert</span>(a);
Code language: JavaScript (javascript)

Javascriptでウィンドウを縮小させる。(Firefox編)

Javascriptと正確にはCSSを使って、ウィンドウをスクリプト側から縮小させる方法です。
Firefoxは、IEやChromeにはある「zoom: 1.0;」のようなCSSがなく、独自に「.MozTransform=”scale(0.1)”;」があります。しかしこれ、ちょっとやっかいで縮小するとウィンドウが中央に配置されて、画面のまわりが余白だらけになってしまいます。これをどうにか左寄せしようと思います。

そのまえに問題です

xが0.1のとき
13000

xが0.2のとき
5800

xが0.5のとき
1440Code language: CSS (css)

このxの数式がなんなのか当ててみましょう。




私は・・わかりませんでした・・・orz
これはワイド画面のディスプレイでとあるページで画面の左上寄せに必要だった余白部分のサイズの数値です。


しょうがないので、Firefoxの縮小の挙動を考えてみることにしました。

ウィンドウの横の長さが980だったとしたら、それを0.8倍にしたら、784。
つまり、もともとのウィンドウのサイズ980-784で196だけ小さくなった。
この196というのは余白分。画面は中央に表示されているので、左と右の2つの幅ということになる。
なので、これを2で割ると、その半分の余白のサイズが求められます。

そしてらできた

<span class="synIdentifier">var</span> htmlElm = <span class="synStatement">document</span>.getElementsByTagName(<span class="synConstant">"html"</span>)<span class="synIdentifier">[</span>0<span class="synIdentifier">]</span>;
htmlElm.style.MozTransform=<span class="synConstant">"scale(1)"</span>;
<span class="synIdentifier">var</span> sx = <span class="synStatement">document</span>.body.clientWidth * 1.0;
<span class="synIdentifier">var</span> sy = <span class="synStatement">document</span>.body.clientHeight * 1.0;
<span class="synIdentifier">var</span> a = 0.5;
htmlElm.style.position = <span class="synConstant">"absolute"</span>;
htmlElm.style.left = <span class="synConstant">"-"</span>+((sx-sx*a)/2.0)+<span class="synConstant">"px"</span>;
htmlElm.style.<span class="synStatement">top</span> = <span class="synConstant">"-"</span>+((sy-sy*a)/1.98)+<span class="synConstant">"px"</span>;
htmlElm.style.MozTransform=<span class="synConstant">"scale("</span>+a+<span class="synConstant">")"</span>;
Code language: HTML, XML (xml)

フレームページの場合はこうする。

var sx = document.getElementById("iframe").contentDocument.body.scrollWidth * 1.0;
var sy = document.getElementById("iframe").contentDocument.body.scrollHeight * 1.0;Code language: JavaScript (javascript)

連想配列とオブジェクトの違い

一瞬頭がこんがらがった。記述の仕方は同じなのに、結果が出てこないし、JSONオブジェクトにも変換できない。どうしてなんだろうと思ったら、自分が記述していたのは連想配列のほうだった。

連想配列はこんなかんじ。

var a = [];
a["hoge"] = 1; //a.hoge = 1;
console.log(a);
//結果:[]Code language: JavaScript (javascript)

オブジェクトはこんなかんじ。

var a = {};
a["hoge"] = 1; //a.hoge = 1;
console.log(a);
//結果:Object > hoge: 1, __proto__: Object >Code language: JavaScript (javascript)

var a = [];は var a = Array();
var a = {}; は var a = Object();


記述は同じだけど、中身の扱いが全く違う別物なので、初歩的ミスながら気づくのにちょっと時間がかかってしまった。