2017-12-10 4 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

기술적으로 나는 하나의 변수를 다른 변수에 할당했습니다. 둘 다 문자열입니다. 가치는 어떻게 다른가요?

그렇기 때문에 innerHTML이 특별합니다. 단순한 가치 속성이 아니라 접근 자 속성입니다. 당신이 그것에 할당 할 때, 당신은 당신이 HTML을 파싱하고 필요한 DOM 노드와 엘리먼트를 생성하는 under-the-covers 함수를 호출하고있다. 그 값을 읽을 때, DOM 트리에 액세스하는 요소부터 시작하여 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>

참고 게다가; 그것은을 가질 수 단지 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는 getter와 setter와 속성이라는 사실은 다음과 같습니다

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

이것은 DOM 트리를 지속적으로 만들고 파괴하고 다시 만들고 숨겨진 함수 호출을번으로 만듭니다. 대신 문자열 을 작성한 다음을 지정하십시오.

+0

감사합니다. 이것은 많은 의미가 있습니다. 단순한 값의 특성이 아니며, 그 뒤에 로직이있는 C# 스타일 속성이 있습니다. 이 경우에는 'el.innerHTML .__ proto__'이 여전히 이것이 _String_ –

+0

이라고 말하면 이상합니다. @ YossiVainshtein : 예, C# 속성과 같습니다. 아니,'el.innerHTML .__ proto__'이'String'이라는 것은 이상한 일이 아닙니다. :-) 당신은 getter 함수 자체가 아닌 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 객체로도 정의 할 수 있습니다). –