【问题标题】:Difference between textContent vs innerTexttextContent 与 innerText 之间的区别
【发布时间】:2016-05-14 18:44:18
【问题描述】:

JavaScript 中的textContentinnerText 有什么区别?

我可以像下面这样使用textContent吗:

var logo$ = document.getElementsByClassName('logo')[0];
logo$.textContent = "Example";

【问题讨论】:

  • @Pointy 所有浏览器都支持的那个是什么?
  • 关于它的good blog post
  • 没有。你必须包含代码来检查哪个存在,然后使用那个。
  • @Pointy 请参考我所指的博文。你的说法不正确,有区别。
  • innerTexttextContent 显然不一样。节点内容中出现的空白会导致两个属性产生不同的内容,br 元素和其他块级渲染后代也会出现。

标签: javascript


【解决方案1】:

innerTexttextContent 之间的主要区别在Kelly Norton's blogpost: innerText vs. textContent 中有很好的概述。您可以在下面找到摘要:

  1. innerText 是非标准的,textContent 是较早标准化的。
  2. innerText 返回节点中包含的可见 文本,而textContent 返回完整 文本。例如,在以下 HTML <span>Hello <span style="display: none;">World</span></span> 上,innerText 将返回“Hello”,而 textContent 将返回“Hello World”。如需更完整的差异列表,请参阅http://perfectionkills.com/the-poor-misunderstood-innerText/ 的表格(在'innerText' works in IE, but not in Firefox 进一步阅读)。
  3. 因此,innerText 更加注重性能:它需要布局信息才能返回结果。
  4. innerText 仅针对HTMLElement 对象定义,而textContent 则针对所有Node 对象定义。

请务必查看此答案下方的信息丰富的 cmets。

textContent 在 IE8- 中不可用,并且在指定节点的所有 childNodes 上使用 nodeValue 的裸机 polyfill 看起来像一个递归函数:

function textContent(rootNode) {
  if ('textContent' in document.createTextNode(''))
    return rootNode.textContent;

  var childNodes = rootNode.childNodes,
      len = childNodes.length,
      result = '';
  
  for (var i = 0; i < len; i++) {
    if (childNodes[i].nodeType === 3)
      result += childNodes[i].nodeValue;
    else if (childNodes[i].nodeType === 1) 
      result += textContent(childNodes[i]);
  }

  return result;
}

【讨论】:

  • 另外值得注意的是:innerText 会将&lt;br&gt; 元素转换为换行符,而textContent 将忽略它们。因此,当使用 textContent 时,两个单词之间只有一个 &lt;br&gt; 元素(并且没有空格)将被连接起来
  • 那么使用setter有什么区别呢?喜欢elem.textContent = 'foobar'elem.innerText = 'foobar'
  • innerTexttextContent在行为上的另一个区别:如果你通过CSS改变一个元素的text-transform,它会影响'innerText'的结果,但不会影响@的结果987654354@。例如:innerText&lt;div style="text-transform: uppercase;"&gt;Hello World&lt;/div&gt; 将是“HELLO WORLD”,而 textContent 将是“Hello World”。
  • 关于点“3”(性能)。我做了一个快速测试,我不认为这是真的。 let allElements = [...document.getElementsByTagName('*')]; t1 = performance.now(); for(let i=0; i&lt;allElements.length; i++){ txt = allElements[i].innerText; } t2 = performance.now(); console.log('innerText', t2-t1); for(let i=0; i&lt;allElements.length; i++){ txt = allElements[i].textContent; } t3 = performance.now(); console.log('textContent', t3-t2); 在控制台执行看看。在某些情况下(例如在这个网站上)textContent 会更好一些,在 mail.google.com 上 - 反之亦然。
  • @ShimonS innerText is much more performance-heavy 是正确的,但要相对地采取:如果 innerText 在平均上比 textContent 慢 100 倍,并且 @ 987654361@ 每次操作需要 1/1000 毫秒,1/10 毫秒对人类来说仍然感觉快。此外,两者之间的有意义的比较只能是元素包含很多隐藏的东西,如 &lt;script&gt;style="display: none;" children
【解决方案2】:

textContent 是唯一可用于文本节点的:

var text = document.createTextNode('text');

console.log(text.innerText);    //  undefined
console.log(text.textContent);  //  text

在元素节点中,innerText 评估
元素,而textContent 评估控制字符:

var span = document.querySelector('span');
span.innerHTML = "1<br>2<br>3<br>4\n5\n6\n7\n8";
console.log(span.innerText); // breaks in first half
console.log(span.textContent); // breaks in second half
&lt;span&gt;&lt;/span&gt;

span.innerText 给出:

1
2
3
4 5 6 7 8

span.textContent 给出:

1234
5
6
7
8

如果内容是用innerText 设置的,则textContent 不能使用带有控制字符(例如换行符)的字符串。另一种方式(使用textContent设置控制字符),所有字符都返回innerTexttextContent

var div = document.createElement('div');
div.innerText = "x\ny";
console.log(div.textContent);  //  xy

【讨论】:

    【解决方案3】:

    对于那些用谷歌搜索这个问题并到达这里的人。我觉得这个问题最明确的答案在 MDN 文档中:https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent

    您可以忘记所有可能让您感到困惑的点,但请记住两件事:

    1. 当您尝试更改文本时,textContent 通常是您要查找的属性。
    2. 当您尝试从某个元素中获取文本时,innerText 近似于用户使用光标突出显示该元素的内容然后复制到剪贴板时所获得的文本。 textContent 为您提供所有可见或隐藏的内容,包括 &lt;script&gt;&lt;style&gt; 元素。

    【讨论】:

    • "此外,由于 innerText 考虑了 CSS 样式,读取 innerText 的值会触发重排以确保最新的计算样式。(重排可能在计算上很昂贵,因此应避免可能。)” “当浏览器必须再次处理和绘制部分或全部网页时,例如在交互式站点上更新之后,就会发生重排。” developer.mozilla.org/en-US/docs/Glossary/ReflowinnerText ReFlow 关系。那些 MDN 文章比其他答案更具解释性。
    【解决方案4】:

    innerTexttextContent 自 2016 年起已标准化。所有 Node 对象(包括纯文本节点)都具有 textContent,但只有 HTMLElement 对象具有 innerText

    虽然textContent 适用于大多数浏览器,但它不适用于 IE8 或更早版本。使用这个 polyfill,它只能在 IE8 上工作。此 polyfill 不适用于 IE7 或更早版本。

    if (Object.defineProperty 
      && Object.getOwnPropertyDescriptor 
      && Object.getOwnPropertyDescriptor(Element.prototype, "textContent") 
      && !Object.getOwnPropertyDescriptor(Element.prototype, "textContent").get) {
      (function() {
        var innerText = Object.getOwnPropertyDescriptor(Element.prototype, "innerText");
        Object.defineProperty(Element.prototype, "textContent",
         {
           get: function() {
             return innerText.get.call(this);
           },
           set: function(s) {
             return innerText.set.call(this, s);
           }
         }
       );
      })();
    }
    

    Object.defineProperty 方法在 IE9 或更高版本中可用,但它在 IE8 中仅适用于 DOM 对象。

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

    https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent

    【讨论】:

    • 这也是它的规范:w3.org/TR/DOM-Level-3-Core/core.html 另外(非常旧的)浏览器支持表 (webdevout.net/browser-support-dom#dom3core) 表明它支持 IE9+,因此对于 IE8 和更早版本,innerText是你的朋友。
    • 其实不支持ie8或者使用polyfill比较好。我在我的帖子中发布了 polyfill
    • 如果不支持Object.defineProperty(),那个 polyfill 如何在 IE8 中工作?
    • 你为什么不更新你的答案? html.spec.whatwg.org/multipage/…
    • 这里引用 MDN 关于 innerText 的一段话——“这个特性最初是由 Internet Explorer 引入的,在被所有主要浏览器厂商采用后,于 2016 年正式在 HTML 标准中指定。”
    【解决方案5】:

    大多数浏览器都支持textContent。 ie8 或更早版本不支持,但可以使用 polyfill

    textContent 属性设置或返回指定节点及其所有后代的文本内容。

    http://www.w3schools.com/jsref/prop_node_textcontent.asp

    【讨论】:

      【解决方案6】:

      除了其他答案中提到的所有差异之外,还有一个我最近才发现的差异:

      尽管据说innerText 属性自 2016 年以来已经标准化,但它表现出浏览器之间的差异:Mozilla 忽略了 innerText 中的 U+200E 和 U+200F 字符(“lrm”和“rlm”),而 Chrome 则没有。

      console.log(document.getElementById('test').textContent.length);
      console.log(document.getElementById('test').innerText.length);
      &lt;div id="test"&gt;[&amp;#x200E;]&lt;/div&gt;

      Firefox 报告 3 和 2,Chrome 报告 3 和 3。

      尚不确定这是一个错误(如果是,在哪个浏览器中)还是只是我们必须忍受的那些古怪的不兼容性之一。

      【讨论】:

      • 哇。惊人地发现!
      【解决方案7】:

      textContent 返回全文并且不关心可见性,而innerText 关心。

      <p id="source">
          <style>#source { color: red; }</style>
          Text with breaking<br>point.
          <span style="display:none">HIDDEN TEXT</span>
      </p>
      

      textContent 的输出:

      #source { color: red; } Text with breakingpoint. HIDDEN TEXT
      

      innerText 的输出(注意innerText 如何识别&lt;br&gt; 之类的标签,并忽略隐藏元素):

      Text with breaking point.
      

      【讨论】:

      • 在IE11中,innerText的行为与textContent的行为相同。
      【解决方案8】:

      textContent 相比,innerText 的另一个有用行为是换行符和多个相邻的空格将仅显示为一个空格,这可以更容易比较字符串。

      但根据您的需要,firstChild.nodeValue 可能就足够了。

      【讨论】:

        【解决方案9】:
        document.querySelector('h1').innerText/HTML/textContent 
        

        .querySelector('h1').innerText - 在里面给我们文本。它对当前显示的内容很敏感,或者忽略隐藏的人员。

        .querySelector('h1').innertextContent - 类似于innerText,但它不关心正在显示的内容或实际显示给用户的内容。它将显示所有内容。

        .querySelector('h1').innerHTML = &lt;i&gt;sdsd&lt;/i&gt; 有效* - 检索完整内容,包括标签名称。

        【讨论】:

        • 有innertextContent吗?
        【解决方案10】:

        innerHTML 甚至会执行 HTML 标签,这可能会导致任何类型的客户端注入攻击,例如基于 DOM 的 XSS。 这是代码sn-p:

        <!DOCTYPE html>
        <html>
            <body>
                <script>
                    var source = "Hello " + decodeURIComponent("<h1>Text inside gets executed as h1 tag HTML is evaluated</h1>");  //Source
                    var divElement = document.createElement("div");
                    divElement.innerHTML = source;  //Sink
                    document.body.appendChild(divElement);
                </script>
            </body>
        </html>
        

        如果您使用 .textContent,它不会评估 HTML 标记并将其打印为字符串。

        <!DOCTYPE html>
        <html>
            <body>
                <script>
                    var source = "Hello " + decodeURIComponent("<h1>Text inside will not get executed as HTML</h1>");  //Source
                    var divElement = document.createElement("div");
                    divElement.textContent = source;  //Sink
                    document.body.appendChild(divElement);
                </script>
            </body>
        </html>
        

        参考:https://www.scip.ch/en/?labs.20171214

        【讨论】:

        • 问题没有提到innerHTML。答案没有提到innerText
        猜你喜欢
        • 2013-10-02
        • 1970-01-01
        • 1970-01-01
        • 2015-07-02
        • 2018-04-22
        • 2013-10-25
        相关资源
        最近更新 更多