E4X traps
散々ハマった後でようやく原典に当たった。そのメモ。
toString
p.innerHTML += <b>NG</b> p.innerHTML += <b>NG</b>.toString() p.innerHTML += <b>OK</b>.toXMLString()
XML.prototype.toString = function toString() this.hasSimpleContent() ? this.text().toString() : this.toXMLString();
hasSimpleContent()
かどうかで挙動が変わる。
replace
<_>OK</_>.replace('*', 'NG') <_>OK</_>.toString().replace('*', 'NG')
javascript:alert([<_>OK</_>.replace('*','NG'),<_>OK</_>.toString().replace('*','NG')])
大抵の文字列メソッドはそのまま呼べるが,XML.prototype.function::replace
があるため replace
はダメ。
empty element
document.body.innerHTML = <><b style="display:none"></b><b>hoge</b></>
とやると何も表示されない。(<b></b>
が <b/>
になり,</b>
は省略出来ないので <b style="display:none"><b>hoge</b></b>
と解釈される。)
間に何か挟めば問題無い。しかし単に空白だと
<o><x/></o> | "<o>\n <x/>\n</o>" |
<o><x></x></o> | "<o>\n <x/>\n</o>" |
<o><x> </x></o> | "<o>\n <x></x>\n</o>" |
<o>{<x> </x>}</o> | "<o>\n <x/>\n</o>" |
javascript:alert([<o><x/></o>,<o><x></x></o>,<o><x> </x></o>,<o>{<x> </x>}</o>])
なんとも不安定な結果に。
XML.prettyPrinting = true <x> </x>.toXMLString() //=> '<x></x>' XML.prettyPrinting = false <x> </x>.toXMLString() //=> '<x> </x>'
XML.prettyPrinting = false
して空白文字の揺れを避けると,今度は子要素無しの <x></x>
を作れなくなる。
<x> </x>.toXMLString().replace(/>\s+</g, '><')
とでもするのが無難?
compound assignment with anyname
.* +=
での要素追加。短く書けるものの効率は悪く
x = <x>t</x> x.* += <a/> // <x>t<a/></x> x.* += <b/> // <x>t<a/><b/></x> x.* += 't' // <x>t<a/><b/>t</x>
テキストノードの追加でハマる。
// この三つは同じ意味 x.* += 't' x.* = x.* + 't' x.setChildren(x.children() + 't')
x.* += XML('t')
でもいいが,こう書くくらいなら x.appendChild('t')
で。
appendChild
Array.reduce('123', function(l, d) l.appendChild(<li>{d}</li>), <ol/>) //=> <ol> <li>1</li> <li>2</li> <li>3</li> </ol>
XML.ignoreWhitespace
入出力両方*1に影響する。
XML.ignoreWhitespace |
true |
false |
---|---|---|
<> <x/> </>.toXMLString() ((XML.prettyPrinting = true )) |
"<x></x>" |
"\n<x></x>\n" |
XML(' <x/> ') |
<x/> |
syntax error |
Global なのでタチが悪い。
「...toXMLString()
」の直前に false
, 「XML(...)
」の直前に true
を心掛ける。
comment and processing-instruction
それぞれ XML.ignoreComments, XML.ignoreProcessingInstructions
を false
にしないと生成できない。
[XML.ignoreComments = XML.ignoreProcessingInstructions = b, [<!---->.nodeKind(), <?_?>.nodeKind()] for each(b in [true, false])].join(' ') //=> text,text comment,processing-instruction
type ambiguity
typeof <x/> //=> "xml" <x/> instanceof XML //=> false <x/> == <x/> //=> true <x/> === <x/> //=> false
厳密には object だが、 primitive のように振る舞う。
__proto__
typeof <_/>.__proto__.__proto__.__proto__ /*...*/ //=> "xml"
E4X@Bugzilla
未完成かつ開発が止まっている。