2017-12-10 5 views
6

私は説明できない奇妙なJavaScriptの動作をしています。innerHTMLと 

は、このコードを考えてみましょう:

var el = document.createElement('div') 
var s = String.fromCharCode(160) 

el.innerHTML = s 

console.log(s)   // prints space 
console.log(el.innerHTML) // prints " " 

は、今私は が非改行スペースであることを知っているが、技術的には、私はちょうど両方が文字列で、別の変数の代入を行いました。 どのように値が異なっていますか?

innerHTMLは特殊な文字列ですか?

どのように動作しますか?これを翻訳する仕組みは何ですか?

答えて

9

技術的には、私はちょうど1つの変数を別の変数に割り当てました。両方とも文字列です。どのように値が違うのですか?

はいのため、innerHTMLは特別です。単純な値プロパティではなく、アクセサープロパティです。あなたがそれに割り当てるとき、あなたはあなたがそれを与えるHTMLを解析し、必要なDOMノードと要素を作成する関数をunder-the-coversで呼んでいます。その値を読むと、アクセスした要素から始まるDOMツリーを再帰的に処理し、そのDOMツリーを表すHTML文字列を作成する別の関数を呼び出しています。

U + 00A0という文字を割り当てている間に、それがDOMテキストノードに変わりました。そこから読み取ると、そのDOMテキストノードは正規の(ブラウザのルールに従って)HTML文字列: としてレンダリングされました。

あなたはinnerHTMLの要素を操作するためにDOMを使用して、単純な値のプロパティではないことを見ることができます。

var target = document.getElementById("target"); 
 
target.innerHTML = "\u00A0"; 
 
console.log(target.innerHTML); // " " 
 
target.appendChild(
 
    document.createElement("span") 
 
); 
 
console.log(target.innerHTML); // "&nbsp;<span></span>"
<div id="target"></div>

注それは、JavaScriptのオブジェクトにアクセサプロパティを定義することは可能だと同じように;それはそれらを持つことができるだけでDOMではありません。

var o = { 
 
    get foo() { 
 
    console.log("foo getter called"); 
 
    return this._foo; 
 
    }, 
 
    set foo(value) { 
 
    console.log("foo setter called"); 
 
    this._foo = value; 
 
    } 
 
}; 
 
console.log("foo: " + o.foo); 
 
o.foo = 42; 
 
console.log("foo: " + o.foo);

このようなコードが悪い習慣である理由innerHTMLはゲッターとセッターを持つプロパティであるという事実がある:

for (var n = 0; n < something.length; ++n) { 
    element.innerHTML += ", " + something[n]; 
} 

これは、DOMツリーを構築してから破棄して再構築し、バンチの隠し関数呼び出しを作成しています。代わりに、の文字列を作成し、次にという文字列を割り当てます。

+0

ありがとう、これは多くの意味があります それは単純な値properyではない、その背後にロジックを持つC#スタイルプロパティのsortofですか? この場合、 'el.innerHTML .__ proto__'はまだこれが_String_ –

+0

であると言って変です。@ YossiVainshtein:はい、C#のプロパティと同じです。いいえ、 'el.innerHTML .__ proto__'が' String'であることは奇妙なことではありません。 :-) getter関数自体ではなく、ゲッター関数(文字列)の**戻り値**で '__proto__'にアクセスしています。 ( 'x = el.innerHTML; x .__ proto __;')と同じです。代わりに、[Object.getOwnPropertyDescriptor(el、 "innerHTML") '](https://tc39.github.io/ecma262/#sec-object.getownpropertydescriptor)の結果を見たいと思うでしょう。 DOMプロパティであれば、ブラウザはその操作をサポートする必要はありません。 (しかし、JSオブジェクトのアクセッサーを見たいと思ったら...) –

3

innerHTMLは、それがgettersetterアクセサ財産だ、単純なプロパティではありません。フードの機能が機能することを意味します。 innerHTMLは、指定された入力をHTMLにシリアライズします。与えられた値を解析し、要素とノードを作成し、それらの要素を要素に追加します。

あなたがシリアライズすることなく、与えられた文字を印刷したい場合は、あなたがtextContentプロパティを使用することができ、この

const DOMElement = { 
 
    value: null, 
 
    set innerHTML(html) { 
 
    console.log(`Setting html: ${html}`); 
 
    // Translate into elements and nodes, then append to the element 
 
    this.value = html; 
 
    }, 
 
    get innerHTML() { 
 
    console.log(`Getting html:`); 
 
    // Translate into string, then return it 
 
    return this.value; 
 
    } 
 
}; 
 

 
DOMElement.innerHTML = '<p>Hello</p>'; 
 
console.log(DOMElement.innerHTML);

のように定義されています。

+0

これは特殊な文字列であり、通常のJavaSciprtオブジェクトの通常のプロパティではありませんか? –

+0

はい、通常のプロパティではありません。フードの下では、指定された値をHTMLスタイルに変換します。ノードまたは要素を作成します。 –

+0

@ YossiVainshtein:これは、「通常」の意味に依存します。 * value *プロパティではなく、アクセサ(この場合はDOMオブジェクトで定義されていますが、JavaScriptオブジェクトでもそうすることができます)を持つプロパティです。 –

関連する問題