Sự khác biệt giữa textContent so với InternalText


156

Sự khác biệt giữa textContentinnerTexttrong JavaScript là gì?

Tôi có thể sử dụng textContentnhư sau:

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

3
Chúng giống nhau, nhưng một số trình duyệt hỗ trợ cái này và cái khác.
Pointy

@Pointy cái mà tất cả các trình duyệt hỗ trợ là gì?
Yehia Awad

6
Một bài đăng blog hay về nó
Tyblitz

4
@Pointy vui lòng tham khảo bài viết trên blog mà tôi đã chỉ. Tuyên bố của bạn là không chính xác, có một sự khác biệt.
Tyblitz

3
innerTexttextContentđược quyết định không giống nhau. Sự xuất hiện của khoảng trắng trong nội dung nút sẽ khiến hai thuộc tính mang lại nội dung khác nhau và do đó sẽ xuất hiện các brphần tử và các hậu duệ được hiển thị ở cấp độ khối khác.
Amn

Câu trả lời:


210

Không có câu trả lời nào khác thành công trong việc cung cấp lời giải thích đầy đủ, vì vậy câu trả lời này. Sự khác biệt chính giữa innerTexttextContentđược phác thảo rất rõ trong blogpost của Kelly Norton: InternalText so với textContent . Dưới đây bạn có thể tìm thấy một bản tóm tắt:

  1. innerTextlà không chuẩn, trong khi textContentđã được chuẩn hóa trước đó.
  2. innerTexttrả về văn bản hiển thị có trong một nút, trong khi textContenttrả về toàn bộ văn bản. Ví dụ: trên HTML sau đây <span>Hello <span style="display: none;">World</span></span>, innerTextsẽ trả về 'Xin chào', trong khi textContentsẽ trả về 'Xin chào thế giới'. Để biết danh sách đầy đủ hơn về sự khác biệt, hãy xem bảng tại http://perfectionkills.com/the-poor-misunderpered-innerText/ (đọc thêm tại 'InternalText' hoạt động trong IE, nhưng không phải trong Firefox ).
  3. Kết quả là, innerTexthiệu năng nặng hơn nhiều: nó đòi hỏi thông tin bố trí để trả về kết quả.
  4. innerTextđược định nghĩa chỉ cho HTMLElementcác đối tượng, trong khi textContentđược xác định cho tất cả Nodecác đối tượng.

Một cách giải quyết textContenttrong IE8- sẽ liên quan đến một hàm đệ quy sử dụng nodeValuetrên tất cả childNodescác nút được chỉ định, đây là một thử tại một 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;
}

16
Cũng đáng chú ý: innerTextsẽ biến <br>các yếu tố thành các ký tự dòng mới, trong khi textContentsẽ bỏ qua chúng. Vì vậy, 2 từ chỉ có một <br>yếu tố giữa chúng (và không có khoảng trắng) sẽ được ghép nối khi sử dụngtextContent
skerit 15/03/18

5
Sau đó, có sự khác biệt khi setter được sử dụng? Thích elem.textContent = 'foobar'vselem.innerText = 'foobar'
Franklin Yu

1
Một sự khác biệt khác trong hành vi giữa innerTexttextContent: Nếu bạn thay đổi thành text-transformphần của CSS, nó sẽ ảnh hưởng đến kết quả của 'InternalText', nhưng không phải là kết quả của textContent. Ví dụ: innerTextof <div style="text-transform: uppercase;">Hello World</div>sẽ là "HELLO WORLD", trong khi textContentsẽ là "Hello World".
Kobi

25

textContent là cái duy nhất có sẵn cho các nút văn bản:

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

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

Trong các nút phần tử, innerTextđánh giá các phần tử <br>, trong khi textContentđánh giá các ký tự điều khiển:

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
<span></span>

span.innerText cho:

1
2
3
4 5 6 7 8

span.textContent cho:

1234
5
6
7
8

Các chuỗi có ký tự điều khiển (ví dụ: nguồn cấp dữ liệu) không khả dụng textContent, nếu nội dung được đặt với innerText. Theo cách khác (đặt các ký tự điều khiển với textContent), tất cả các ký tự được trả về cả với innerTexttextContent:

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


20

Cả hai innerText& textContentđược chuẩn hóa kể từ năm 2016. Tất cả Nodecác đối tượng (bao gồm các nút văn bản thuần túy) có textContent, nhưng chỉ HTMLElementcác đối tượng có innerText.

Mặc dù textContenthoạt động với hầu hết các trình duyệt, nó không hoạt động trên IE8 hoặc sớm hơn. Sử dụng polyfill này để nó chỉ hoạt động trên IE8. Polyfill này sẽ không hoạt động với IE7 hoặc sớm hơn.

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);
       }
     }
   );
  })();
}

Các Object.definePropertyphương pháp là availabe trong IE9 hoặc lên, tuy nhiên nó có sẵn trong IE8 cho đối tượng DOM chỉ.

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


2
Đây cũng là thông số kỹ thuật cho nó: w3.org/TR/DOM-Level-3-Core/core.html Ngoài ra, bảng hỗ trợ trình duyệt (rất cũ) ( webdevout.net/browser-support-dom#dom3core ) gợi ý rằng nó được hỗ trợ cho IE9 +, vì vậy đối với IE8 trở lên, innerTextlà bạn của bạn.
geekonaut

Trên thực tế, đó là một ý tưởng tốt hơn để không hỗ trợ eg8 hoặc sử dụng polyfill. Tôi đã đăng polyfill trong bài đăng của mình
Richard Hamilton

1
Làm thế nào polyfill đó có thể hoạt động trong IE8 khi nó không hỗ trợ Object.defineProperty()?
Pointy

2
Tại sao bạn không cập nhật câu trả lời của bạn? html.spec.whatwg.org/multipage/ Từ
caub

3
Dưới đây là một trích dẫn của MDN về InternalText - "Tính năng này ban đầu được giới thiệu bởi Internet Explorer và được chỉ định chính thức trong tiêu chuẩn HTML vào năm 2016 sau khi được tất cả các nhà cung cấp trình duyệt lớn áp dụng."
cuộc trò chuyện

15

Đối với những người đã googled câu hỏi này và đến đây. Tôi cảm thấy câu trả lời rõ ràng nhất cho câu hỏi này là trong tài liệu MDN: https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent .

Bạn có thể quên tất cả những điểm có thể làm bạn bối rối nhưng hãy nhớ 2 điều:

  1. Khi bạn đang cố gắng thay đổi văn bản, textContentthường là tài sản bạn đang tìm kiếm.
  2. Khi bạn đang cố lấy văn bản từ một số phần tử, hãy innerTextxấp xỉ văn bản mà người dùng sẽ nhận được nếu họ tô sáng nội dung của phần tử bằng con trỏ và sau đó sao chép vào bảng tạm. Và textContentcung cấp cho bạn mọi thứ, có thể nhìn thấy hoặc ẩn, bao gồm <script><style>các yếu tố.

11

textContent được hỗ trợ bởi hầu hết các trình duyệt. Nó không được hỗ trợ bởi eg8 hoặc sớm hơn, nhưng một polyfill có thể được sử dụng cho việc này

Thuộc tính textContent đặt hoặc trả về nội dung văn bản của nút được chỉ định và tất cả các hậu duệ của nó.

Xem http://www.w3schools.com/jsref/prop_node nhiệtcontent.asp


0

textContent trả về văn bản đầy đủ và không quan tâm đến khả năng hiển thị, trong khi InternalText thì có.

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

Đầu ra của textContent:

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

Đầu ra của InternalText (lưu ý cách thức bên trong nhận biết các thẻ như <br>và bỏ qua phần tử ẩn):

Text with breaking point.

Trong IE11, hành vi của InternalText giống như của textContent.
Sebastian

0

Ngoài tất cả những khác biệt được đặt tên trong các câu trả lời khác, đây là một điều khác mà tôi chỉ phát hiện ra gần đây:

Mặc dù innerTexttài sản được cho là đã được chuẩn hóa từ năm 2016, nhưng nó thể hiện sự khác biệt giữa các trình duyệt: Mozilla bỏ qua các ký tự U + 200E và U + 200F ("lrm" và "rlm") innerText, trong khi Chrome thì không.

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

Firefox báo cáo 3 và 2, Chrome báo cáo 3 và 3.

Không chắc chắn nếu đây là một lỗi (và nếu vậy, trong trình duyệt nào) hoặc chỉ là một trong những không tương thích kỳ quặc mà chúng ta phải sống cùng.


-1

InternalHTML sẽ thực thi ngay cả các thẻ HTML có thể gây nguy hiểm cho bất kỳ loại tấn công tiêm chích phía máy khách nào như XSS dựa trên DOM. Đây là đoạn mã:

<!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>

Nếu bạn sử dụng .textContent, nó sẽ không đánh giá các thẻ HTML và in dưới dạng Chuỗi.

<!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>

Tham khảo: https://www.scip.ch/en/?labs.20171214

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.