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 オブジェクトの対応するプロパティを変更すること、そしてその逆を意味する。
ちゃんと説明しとくと、この動作の奇妙さは
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 は関数を返す関数です)
便利なので入れたい気もするけど、うまく書かないと混乱するのでむずかしい。
✖
最近 www.lowreal.net のページの作り直しをしている。もともと、1ページだけ好き勝手いろいろやってみるためのものだったので大分適当だったのを、もうちょいちゃんと自己紹介用のページに使えるようにするという狙いと、あとまぁやっぱ好き勝手またやってみたくなったという感じで、久しぶりに HTML のマークアップから CSS、 JS までいろいろと使った。
今回は、普通に内容情報を変更をするとともに、ページ単体でのスマートフォン (Mobile Webkit = iPhone, Android) 対応と、実験的に巨大スクリーン対応を入れている。
スマートフォン対応は大抵のまともなサイトは最近入れはじめているし、小さいスクリーン用に別の情報コントロールを入れるのはまぁ正しいと思うので、適度にそうやった。このページは twitter からの流入が一番多いし意味もある程度はありそう。
巨大スクリーン対応は、デカイ画面に全画面にすると余白があきすぎで滑稽になるのがあまりにもあれなので (かつてはまぁリキッドレイアウトならば、利用者が適時ウィンドウサイズを変えればいいだろうと思っていたけれども、そうはいっても、という感じなので)、特定サイズ以上のウィンドウサイズになったら、ページ全体を拡大するように (1240 を基準として、拡大率が 1.4 倍以上になるなら適用 = 1920程度から拡大される) してみた。(WebKit, Gecko のみ) この対応が正しい対応かどうかはちゃんと考えきれてはいない。フォントサイズが固定ではなく、エラスティックレイアウトなので、ピクセル基準ではなくフォントサイズ基準にすべきだけどとりあえず。
PC で開いたとき、一番上の画像を切り替わるようにしてみたけど、なんとなく実装したらおもいのほか簡単にできてびっくりした。簡単に管理したいなーと思ったので、切り替わる画像は fotolife の特定 ID の RSS からとっていて、あとは fotolife にアップロードしていくだけで切り替わる写真が変化していくので、管理も楽な感じになった。fotolife のフィードなら何でもいけるのでブログパーツみたいにできそう。
関連エントリー
- モールスコードを再生できるだけのページ をつくった。 http://play-morse.lowreal.net/ だいたい、符号って長点短点を可視化して見せてしまっていることが多...
- サイトの画像サイズを再びアップグレード 昨年の4月にデザインの調整ということで、写真の最大サイズを 1024px まで上げていたのですが、これは Google Photos の無料...
- ✖ Chrome やら Firefox やら、requestFullscreen に対応しつつあるブラウザでは写真をクリックしたときにそれを使う...
- Adsense の新しい広告ユニット 最近になって「関連コンテンツ」と「ページ単位の広告」というのが beta になって登場した。サイト最適化と同時にこれらも有効にしてみたりして...
- Gist に置いた JavaScript のベンチマークをとる デモ textContent innerText $().text() の比較ベンチ for of と単純な for の比較ベンチ ある要素...
✖
✖
5つ以上スターを連打するとグリーンスターつけるように変える Greasemonkey script
5つ以上連打しようとすると勝手にグリーンスターを消費するようになるグリモンです。
グリーンスターに切り替わるとつく速度が落ちますが、連打したぶんはちゃんとつくので待っていてください (色つきスターはリクエストが増えるみたいなので純粋につけるのに時間がかかってます)
最近 Java の Executors にラブなので SingleThreadExecutor みたいなやつをつくってやってます。
✖
✖
一方的に、高台から発砲して人を殺すことを自覚してるのかしてないのか
✖
[tabelog:896885:detail]
割とよく行きます。
[tabelog:900921:detail]
この前 nanto_vi さんと motemen さんと一緒に行きました。パフェうまかったです (京大学食)
[[たべぞうさん、お楽しみ袋欲しい!]]
関連エントリー
- 『いなり、こんこん、恋いろは。』よしだもろへ いなり、こんこん、恋いろは。 (1) (角川コミックス・エース 326-1) cho45 よしだ もろへ ★ 3.0 / 5.0 cho45...
- YONGNUO YN600Air 5500K モデルを買ってみた YONGNUO YN600Air LED ビデオライト 5500K SMD LED搭載 超薄 カメラ ビデオカメラ用 補助照明 撮影用 Ca...
- Raspberry Pi がきたのでセットアップして I2C デバイスを読むところまで Raspberry Pi だ! ππだ!! Raspberry Pi は約5000円ぐらいで買うことができるカードサイズの Linux パソ...
- アンテナアナライザの回路 - ブリッジの三つの電位差を測るタイプ http://www.rigexpert.com/index?s=articles&f=aas ブリッジの50Ω/50Ωで分圧したほうの電位...
- Klipper 用の raspiberry pi のカスタマイズ Raspberry Pi の負荷が高くなると mcu との通信に支障がおこり、最悪プリンタが止まる。なので cron をできるだけ止める a...















