về mặt kỹ thuật, tôi chỉ gán một biến cho một biến khác, cả hai đều là chuỗi. Làm thế nào đến các giá trị khác nhau?
Vì có, innerHTML
là đặc biệt. Nó không chỉ là một thuộc tính giá trị đơn giản, nó là một tài sản accessor. Khi bạn gán cho nó, bạn đang gọi một hàm nằm trong phạm vi phân tích cú pháp HTML mà bạn cung cấp và tạo các nút và các phần tử DOM cần thiết. Khi bạn đọc giá trị của nó, bạn đang gọi một hàm khác nằm trong phạm vi bao quát qua cây DOM bắt đầu từ phần tử mà bạn truy cập nó và xây dựng một chuỗi HTML biểu diễn cây DOM đó.
Vì vậy, trong khi bạn gán ký tự U + 00A0 cho nó, nó đã được chuyển thành nút văn bản DOM; và khi bạn đọc từ đó, nút văn bản DOM được hiển thị dưới dạng chuẩn (theo quy tắc của trình duyệt đó) Chuỗi HTML:
.
Bạn có thể thấy rằng innerHTML
không chỉ là một tài sản giá trị đơn giản bằng cách sử dụng DOM để thao tác các phần tử:
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>
Lưu ý rằng nó có thể để xác định tính chất accessor trong đối tượng JavaScript cũng; nó không chỉ là DOM có thể có họ:
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);
Thực tế là innerHTML
là một tài sản với một getter và setter là lý do tại sao mã như thế này là thực hành kém:
for (var n = 0; n < something.length; ++n) {
element.innerHTML += ", " + something[n];
}
Đó là liên tục xây dựng và sau đó phá hủy và xây dựng lại một cây DOM và thực hiện một bó của các cuộc gọi chức năng ẩn. Thay vào đó, bạn sẽ tạo chuỗi, rồi gán nó.
Nguồn
2017-12-10 09:45:08
Cảm ơn, điều này có ý nghĩa rất nhiều, Vì vậy, nó không phải là một giá trị đơn giản thích hợp, nó là loại tài sản phong cách C# với logic đằng sau nó? Trong trường hợp này, thật lạ khi 'el.innerHTML .__ proto__' vẫn nói đây là _String_ –
@YossiVainshtein: Có, giống như thuộc tính C#. Không, không lạ khi 'el.innerHTML .__ proto__' là' String'. :-) Bạn đang truy cập '__proto__' trên giá trị trả về ** của hàm getter (là một chuỗi), không phải là hàm getter. (Giống như 'x = el.innerHTML; x .__ proto __;'). Thay vào đó, bạn muốn xem kết quả của ['Object.getOwnPropertyDescriptor (el," innerHTML ")'] (https://tc39.github.io/ecma262/#sec-object.getownpropertydescriptor), nhưng vì nó thuộc tính DOM, trình duyệt không phải hỗ trợ thao tác đó trên đó. (Nhưng nếu bạn muốn nhìn thấy người truy cập của đối tượng JS ...) –