2010年 02月 21日



JavaScript、仮引数で宣言した変数へ代入したあとの arguments の挙動

さて問題です。以下のコードで alert されるのは何でしょう!!

(function (x) {
  x = 2;
  alert(arguments[0]);
})(1);


答えはやってみてください。ビビりました。どうやら arguments オブジェクトは、変数の参照 (値の参照ではなく) を持っています。

ECMAScript 3rd Edition 日本語訳から根拠を探すと、ちゃんと書いてありました。

  • 0 以上 length プロパティの値未満の整数 arg それぞれについて、属性 { DontEnum } のプロパティ ToString(arg) が作成される。このプロパティの初期値は対応するパラメータの呼出側に供給される実際の値である。最初の実際のパラメータ値が arg = 0、2 番目は arg = 1, 以下同様である。arg が Function オブジェクトの仮引数の数より小さい場合、このプロパティは Activation オブジェクトの対応するプロパティとその値を共有する。このことは、このプロパティの変更が Activation オブジェクトの対応するプロパティを変更すること、そしてその逆を意味する。
http://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/10_Execution_Contexts.html#section-10.1.8

ちゃんと説明しとくと、この動作の奇妙さは

var obj = new Object();

obj[0] = 1;
obj.foo = obj[0];

obj[0] = 2;
alert(obj.foo); //=> 1

var baz = new Object();
baz.foo = obj[0];

obj[0] = 3;
alert(baz.foo); //=> 2

というあたり前 (に感じる) 挙動崩れるところです。普通、オブジェクトの別プロパティに代入したら、他のプロパティの値も同時に変わることなんてことはありえないし、別オブジェクトのプロパティが変わるなんてもってのほかですが、Activation オブジェクトの引数関係のプロパティだけは違う、ということです。

Activation オブジェクトはそもそも何かというと、変数を保持するオブジェクトです。この、隠れたオブジェクトを見えるようにしたコードを書くと、冒頭のコードは

(function (x) {
  // // Variable Instantiation
  // var a = new Activation(); 
  // a.arguments = { };
  // a.arguments[0] = 1;
  // a["x"] = a.arguments[0];
  // // End

  // a["x"] = 2;
  x = 2;

  // alert(a.arguments[0]);
  alert(arguments[0]);
})(1);

のように (実際は Activation オブジェクトにはアクセスできない) なり、そもそも仮引数 x が保持されているオブジェクトと、渡された引数第一番目の arguments[0] は別々のオブジェクトなのにも関わらず、値が共有されて相互作用をします。

これは「変数」を保持している「オブジェクト」が存在するという仕様上の説明からすると、一貫性がない不可解な動作です。

JSDeferred Deferred.chain

http://lab.hisasann.com/addCommand/index.html を見ていて、next().next() 以外に、こういう風に書けても別にいいよなぁと思ったので実装を書いてみた。next().next() はめんどい割とめんどいし

git master HEAD には今のところ Deferred.chain() として入ってる。これと Deferred.connect() の変数バインドを組み合せて、addCommand.js のデモ相当をしてみた。

それっぽいとこを抜きだすと

Deferred.define();

var img1 = $("#img1"),
	img2 = $("#img2"),
	img3 = $("#img3");
(function() {
	var callee  = arguments.callee;

	var animate = function (target, prop, speed, easing) {
		return Deferred.connect(target, "animate", { args: [ prop, speed, easing ] });
	};

	Deferred.chain(
		animate(img1, {
			opacity: 0, top: 90 + "px", left: 260 + "px"
			}, 1000, "easeInOutCirc"),
		animate(img2, {
			opacity: 0, top: 170 + "px", left: 450 + "px"
			}, 1000, "easeInOutCirc"),
		animate(img3, {
			opacity: 0, top: 260 + "px", left: 620 + "px"
			}, 1000, "easeInOutCirc"),
		[
			animate(img1, {
				opacity: 1, top: 0 + "px", left: 0 + "px"
				}, 1000, "easeInBack"),
			animate(img2, {
				opacity: 1, top: 0 + "px", left: 0 + "px"
				}, 1000, "easeInBack"),
			animate(img3, {
				opacity: 1, top: 0 + "px", left: 0 + "px"
				}, 1000, "easeInBack")
		],
		function () {
			return wait(0.5).next(callee);
		},
		function error (e) {
			alert(e);
		}
	);
})();

となっていて、デモのコードとほぼ同じになる。エラーをキャッチする関数には function error() としておくルールがある。

キモは animate() を実行した時点ではアニメーションは実行されず、アニメーションを実行する関数を返すだけのところです。(Deferred.connect は関数を返す関数です)

便利なので入れたい気もするけど、うまく書かないと混乱するのでむずかしい。

2010年 02月 20日

最近 www.lowreal.net のページの作り直しをしている。もともと、1ページだけ好き勝手いろいろやってみるためのものだったので大分適当だったのを、もうちょいちゃんと自己紹介用のページに使えるようにするという狙いと、あとまぁやっぱ好き勝手またやってみたくなったという感じで、久しぶりに HTML のマークアップから CSS、 JS までいろいろと使った。

今回は、普通に内容情報を変更をするとともに、ページ単体でのスマートフォン (Mobile Webkit = iPhone, Android) 対応と、実験的に巨大スクリーン対応を入れている。

スマートフォン対応は大抵のまともなサイトは最近入れはじめているし、小さいスクリーン用に別の情報コントロールを入れるのはまぁ正しいと思うので、適度にそうやった。このページは twitter からの流入が一番多いし意味もある程度はありそう。

巨大スクリーン対応は、デカイ画面に全画面にすると余白があきすぎで滑稽になるのがあまりにもあれなので (かつてはまぁリキッドレイアウトならば、利用者が適時ウィンドウサイズを変えればいいだろうと思っていたけれども、そうはいっても、という感じなので)、特定サイズ以上のウィンドウサイズになったら、ページ全体を拡大するように (1240 を基準として、拡大率が 1.4 倍以上になるなら適用 = 1920程度から拡大される) してみた。(WebKit, Gecko のみ) この対応が正しい対応かどうかはちゃんと考えきれてはいない。フォントサイズが固定ではなく、エラスティックレイアウトなので、ピクセル基準ではなくフォントサイズ基準にすべきだけどとりあえず。

PC で開いたとき、一番上の画像を切り替わるようにしてみたけど、なんとなく実装したらおもいのほか簡単にできてびっくりした。簡単に管理したいなーと思ったので、切り替わる画像は fotolife の特定 ID の RSS からとっていて、あとは fotolife にアップロードしていくだけで切り替わる写真が変化していくので、管理も楽な感じになった。fotolife のフィードなら何でもいけるのでブログパーツみたいにできそう。

2010年 02月 18日


2010年 02月 17日





5つ以上スターを連打するとグリーンスターつけるように変える Greasemonkey script

5つ以上連打しようとすると勝手にグリーンスターを消費するようになるグリモンです。

グリーンスターに切り替わるとつく速度が落ちますが、連打したぶんはちゃんとつくので待っていてください (色つきスターはリクエストが増えるみたいなので純粋につけるのに時間がかかってます)

最近 Java の Executors にラブなので SingleThreadExecutor みたいなやつをつくってやってます。

2010年 02月 16日




一方的に、高台から発砲して人を殺すことを自覚してるのかしてないのか

[tabelog:896885:detail]

割とよく行きます。


[tabelog:900921:detail]

この前 nanto_vi さんと motemen さんと一緒に行きました。パフェうまかったです (京大学食)


[[たべぞうさん、お楽しみ袋欲しい!]]