Opera の attachEvent は addEventListener のエイリアスだと思う


think49
Opera の attachEvent は addEventListener のエイリアスっぽいなあ。実行順が保証される上に { handleEvent: ... } まで通る。
think49
event.target === event.srcElement, event.currentTarget === this が両方とも true になる。
think49
event.preventDefault があり、'returnValue' in event === false
think49
event.stopPropagation があり、'cancelBubble' in event === true
think49
Opera 11.01 の実装は addEventListener に近い。
IE の attachEvent 用に書いたコードがそのまま通る可能性はそれほど高くないと思う…。

var でDontDelete属性が付与されるのは ES3 まで


think49
JavaScript Coding Guidelines for Mac OS X: メモリとパフォーマンスの検討事項
think49
@ そもそも、VariableStatement はDontDelete属性を付与するから delete できないはず…と思ったが、それは までの仕様らしい。
think49
@ ではDontDelete属性が存在しない。従って、VariableStatement で宣言した変数も削除できる。
.2
think49
@ ということは、クロージャによる上位スコープの変数参照も delete で解放できそうだ。重宝しそうなので、覚えておこう…。

compatible-event.js 制作記録


think49
イベントリスナについて教えてください - Yahoo!知恵袋
/
attachEvent で実行順を保証したいらしいが、これは難問。handleEvent をキャッシュする必要があると思う…。
think49
@ まだ作成中だけど gist にポストした。attachEvent の実行順は保証されてなくて循環参照対策は実装済み。
think49
@ 7割ぐらい完成したので version 0.7.0 にした。
think49
@ attachEvent における実行順の保証は完成。
あとは JScriptEvent の挙動を DOM Events の仕様に合わせよう。event.preventDefault とか {handleEvent: fn} とか。
think49
textareaSelectEndPoint.js Firefox, Google Chrome で動かないと報告を頂いたけど、どのよう修正すればいいのかわからないでいる…。
rikuba
@ 21行目と120行目、arguments[0]を渡すのを忘れているのでは。
think49
@ ご指摘ありがとうございます。すっかり忘れてました…。修正しておきます。
think49
@ arguments[0] の不具合修正及び、{handleEvent: fn} に対応。コメント欄に解説を加えた。
think49
@ DOM Events の一部を実装した。(@ 0.9.1b) /
event.target, event.currentTarget, event.preventDefault, event.stopPropagation に対応している。
think49
ただし、event.srcElement === null になる不具合への対策(event.target への適切なノード初期化)はまだ甘い。
think49
window-load ,window-unload, document-DOMContentLoaded 時に event.target === document にする実装にしたが、まだ対応すべきイベントタイプがあると思われる。

"use strict"; はグローバルコードに書いても良い

JSLint ではグローバルコードに 'use strict'; を書くとエラーになるが、ECMAScript 5 違反ではないらしい。(おそらく、Crockford氏の独自の思想によるエラーだと思う)


think49
'use strict'; はグローバルコードに書いてはいけないんだったかな。JSLint で怒られる…。
think49
"- Global code is strict global code if it begins with a Directive Prologue that contains a Use Strict ..."
think49
@ グローバルコードで 'use strict'; して問題ないことを確認した。勿論、"use strict"; でも良い。
.1
think49
(function () { 'use strict'; })(); // JSLint は "Move the invocation into the parens that contain the function." のエラーを出力する。なぜ…?

XML宣言 (XMLDecl) は処理命令 (PI) ではない

XML宣言が PROCESSING_INSTRUCTION_NODE だと思っていて、以下のXHTML文書を書いていました。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
<head>
  <!--
    /**
     * サーバは次のHTTPヘッダを出力しています。
     * Content-Type: application/xhtml+xml; charset=UTF-8
     */
  -->
  <title>XHTML5</title>
</head>
<body>
  <script type="application/javascript"><![CDATA[
  console.log(document.firstChild.nodeType === Node.DOCUMENT_TYPE_NODE);                                                                    // true
  console.log(document.evaluate('child::processing-instruction()', document, null, 7, null).snapshotLength);                                // 0
  console.log(document.createProcessingInstruction('xml', 'version="1.0" encoding="UTF-8"').nodeType === Node.PROCESSING_INSTRUCTION_NODE); // true
  ]]></script>
</body>
</html>

しかし、XML宣言は PROCESSING_INSTRUCTION_NODE ではないので document からノードとして認識されません。
XML宣言の情報は Interface Document (DOM L3 Core) のプロパティとして定義されています。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
<head>
  <title>XHTML5</title>
</head>
<body>
  <script type="application/javascript"><![CDATA[
  console.log(document.xmlVersion);    // "1.0"
  console.log(document.xmlEncoding);   // "UTF-8"
  console.log(document.xmlStandalone); // true
  ]]></script>
</body>
</html>


think49
いい方法が見つからないなあ。/ JavaScriptでのXML解析について質問です。 JavaScriptXMLファイルを読み込んで... - Yahoo!知恵袋
think49
XPath で PROCESSING_INSTRUCTION_NODE を得られると思ったら snapshotLength が 0 になってしまった。XPath式が間違ってるのかな。
think49
document.firstChild が PROCESSING_INSTRUCTION_NODE ではなく、DOCUMENT_TYPE_NODE になる。
think49
document.createProcessingInstruction('xml', 'version="1.0" encoding="UTF-8"'); は使えるので、PROCESSING_INSTRUCTION_NODE を認識しないわけではなさそう。
think49
@ ありがとうございます。2.6 Processing Instructions も合わせて読んで理解できました。
think49
" 'XML'や'xml'などの対象名は、この仕様書のこのバージョン及び将来のバージョンにおける標準化の為に予約されている。処理命令対象の正式な宣言の為に、XML記法機構が使われる事もある。"
think49
XMLDecl の <?xml version="1.0"?> と PI の <?xml version="1.0"?> は別物。
ただし、PITarget の "XML", "xml" は予約されており、将来のバージョンで使われる可能性がある。
think49
PITarget に "xml" は「使うべきではない」(SHOULD NOT) または「使ってはならない」(MUST NOT) と読んだ方がいいのだろう…。

String(value) と value += ''; の違い


think49
読んでる。/ Togetter - 「JavaScript の算術演算子と数値変換」
think49
@ arg = +arg; で ToNumber が呼び出されるというお話。これは Number() と同じ効果がある。
think49
@ ! は ToBoolean 演算子を呼び出して結果を反転する。従って、!! で Boolean() と同じ結果となる。
think49
@ arg += ''; は arg のプリミティブ値に ToString 演算子を適用する。これは String() と結果が異なる。
( の nanto_vi さんのコメントが参考になる)
think49
@ はいー。型変換について調査していたら引っかかりました。
think49
@ それでもこの手法がよくとられるのはプリミティブ値と toString値 (と便宜上置いておく)の値が同値の場合に使われるからだと思う。
think49
@ Number型の値の場合はそれで問題なかった。数値演算はプリミティブ値を元に行われるので必ず同値となる。
think49
@ 実際はないけれども、Object.prototype.toNumber なんてメソッドが定義されていたら同じ問題が出てきたと思う。
think49
@ 実証コードを書いてみた。
think49
"valueOf メソッドはその this 値を返す。"
(ES3: 15.2.4.4 Object.prototype.valueOf)
think49
@ console.log(({}).valueOf() + ''); は console.log(({}).valueOf().toString() + ''); になるから問題ないんだなー。

条件付きコメントと条件付きコンパイルの違い


think49
jQuery で条件付きコメントを応用して、MSIE のバージョンを得る方法が書かれたコードがどこかにあったと思うけど忘れてしまった…。github にコードが上がっていて何かのブログ記事で見た覚えがある。
think49
@ こんな感じだったはず。
あのブログ記事はどこだったかなー。jQuery を解読した海外のブログを翻訳したまとめだった気がする。
think49
MSIE で実装別に処理を分ける方法に「条件付きコメント」と「条件付きコンパイル」があるけど、この2つは別物なんだなあ。
前者を "UA Detection" とするなら、後者は "ScriptEngine Detection" というべきか。
think49
@ IE6 を判定する場合、IE6 (jscript_version == 5.6 or 5.7) を判定したいのか、IE6 (jscript_version == 5.6) を判定したいのか、予め調査する必要があるが、正直面倒な気がする。
think49
@JScriptエンジンのバージョンに依存する問題」なのか、「IEのバージョンに依存する問題」なのか判断するためには IE6 (Windows XP SP2) と IE6 (Windows XP SP3) の両方を検証する必要があるが、どう考えても手間がかかる。
think49
@ そんなところに手間をかけるぐらいなら、"Feature Detection" にした方が能率が上がっていいんじゃないかなー。
think49
回答した。/
IE6だけの判定、IE7だけの判定について | OKWave

(2012/04/15 13:21追記)
条件付きコメントは IE10 から廃止される予定です。