我有一个奇怪的JavaScript行为,我无法解释。
考虑以下代码:
var el = document.createElement('div')
var s = String.fromCharCode(160)
el.innerHTML = s
console.log(s) // prints space
console.log(el.innerHTML) // prints " "
现在我知道 
是不间断的空间,但从技术上讲,我只是将一个变量赋值给另一个变量,两者都是字符串。
为什么价值观不同?
innerHTML
是一种特殊的字符串还是什么?
它是如何工作的?翻译这个的机制是什么?
答案 0 :(得分:10)
从技术上讲,我只是将一个变量赋值给另一个变量,两者都是字符串。为什么价值观不同?
因为是的,innerHTML
很特别。它不仅仅是一个简单的值属性,它还是一个 accessor 属性。当你分配给它时,你正在调用一个函数,它解析你给它的HTML并创建必要的DOM节点和元素。当你读取它的值时,你正在调用另一个函数,它从你访问它的元素开始遍历DOM树,并构建一个表示该DOM树的HTML字符串。
所以当你为它分配字符U + 00A0时,它变成了一个DOM文本节点;当你从中读取时,该DOM文本节点被渲染为规范(根据浏览器的规则)HTML字符串:
。
通过使用DOM来操作元素,您可以看到innerHTML
不仅仅是一个简单的值属性:
var target = document.getElementById("target");
target.innerHTML = "\u00A0";
console.log(target.innerHTML); // " "
target.appendChild(
document.createElement("span")
);
console.log(target.innerHTML); // " <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
是一个带有getter和setter的属性,这就是为什么这样的代码很糟糕的原因:
for (var n = 0; n < something.length; ++n) {
element.innerHTML += ", " + something[n];
}
这是不断构建然后销毁和重建DOM树并进行隐藏函数调用的束。相反,你要构建字符串,然后分配它。
答案 1 :(得分:3)
innerHTML
不是一个简单的属性,它是一个带有getter
和setter
的访问者属性。意味着引擎盖下的功能。 innerHTML
将给定输入序列化为HTML。它解析给定的值,创建元素和节点,然后将这些元素附加到元素。
它定义如下
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);
如果要在不进行序列化的情况下打印给定字符,可以使用textContent
属性。