Skip to content

HTMLElement.innerText和Node.textContent有什么区别?

JavaScript提供了两个属性,你可以用它们来访问元素的文本内容Node.textContentHTMLElement.innerText。在大多数情况下,这两个属性似乎可以互换使用。实际上,许多开发人员在使用它们时是可以互换的,而不知道它们之间存在重要的区别。

相似之处

在深入讨论区别之前,我认为先确定这两个属性的相似之处是有帮助的。这也将阐明它们在大多数情况下的使用方式。

假设你有一个包含一些文本的HTML元素:

<p id="greeting">嗨!我的名字是<strong>Bubbles</strong>。</p>

这两个属性都将返回元素的文本内容,包括任何子元素的文本内容。它们还将忽略元素内容中可能存在的任何HTML标签。而且,它们也可以用于设置元素的文本内容

const greeting = document.getElementById('greeting');

greeting.innerText; // "嗨!我的名字是Bubbles。"
greeting.textContent; // "嗨!我的名字是Bubbles。"

greeting.innerText = '你好!'; // <p id="greeting">你好!</p>
greeting.textContent = '嗨!'; // <p id="greeting">嗨!</p>

差异

到目前为止,这两个属性似乎做的是完全相同的事情。实际上,它们都提供了一些方便的功能,使它们非常有用。然而,当元素的内容稍微复杂一些时,它们开始展示出一些差异。

以下面的HTML元素为例:

<div class="card">
  <style>
    p { color: red; }
    strong { text-transform: uppercase; }
    small { display: none; }
  </style>
  <p>Hi   there!<br />My name is <strong>Bubbles</strong>.</p>
  <small>And I'm a <strong>dog</strong>.</small>
</div>

让我们来看看这两个属性的输出,看看它们之间的区别。

const card = document.querySelector('.card');

card.innerText;
/*
"Hi there!
My name is BUBBLES."
*/

card.textContent;
/*
"

    p { color: red; }
    strong { text-transform: uppercase; }
    small { display: none; }

  Hi   there!My name is Bubbles.
  And I'm a dog.
"
*/

在这种情况下,它是截然不同的,对吧?HTMLElement.innerText应该大致上与用户在浏览器中看到的内容相匹配。另一种思考方式是,它的输出应该与用户选择元素内容并将其复制到剪贴板时所得到的内容非常接近。

首先要注意的是,根据这个定义,隐藏的元素会被忽略。这适用于不渲染的元素,如<style><script>,也适用于使用CSS隐藏的元素。在这个例子中,<small>元素是隐藏的,所以它不会包含在HTMLElement.innerText的输出中。

其次,HTMLElement.innerText的输出是规范化的。这意味着所有的空白字符都被折叠成一个空格,所有的换行符都被替换成一个换行符。如果存在<br>标签,它们也会被保留,所以它们会被替换为一个换行符。

我想要强调的最后一点是,HTMLElement.innerText会对元素的内容应用文本转换。在这个例子中,<strong>元素被转换为大写字母,所以HTMLElement.innerText的输出反映了这一点。

另一方面,Node.textContent返回元素的确切文本内容,包括任何空白字符和换行符。然而,<br>标签会被删除而没有任何替换。它还包括任何隐藏元素的文本内容,如<style><script>,并且不应用任何文本转换。

性能

但是,等等!还有更多!虽然HTMLElement.innerText似乎是一个明智的选择,但它带有一个性能注意事项。为了确定浏览器渲染的内容,必须考虑CSS,从而触发回流。这可能是计算上昂贵的,并且可能导致意外的性能瓶颈。

在我看来,一个好的经验法则是,如果可能的话,优先使用Node.textContent来处理纯文本元素。对于更复杂的元素,尝试确定它们如何受到布局和用户交互的影响。例如,一个只渲染一次且不会被修改的复杂元素,可以使用HTMLElement.innerText,但可以将输出存储在一个变量中并重复使用。

结论

HTMLElement.innerTextNode.textContent是两个非常相似的属性,可以用于访问和操作元素的文本内容。然而,它们在一些重要的方面有所不同,您应该了解这些差异,以选择最适合您需求的方法。始终检查您的用例,并考虑您选择的性能影响。