Есть задача: при отсутствии textContent'а - перенять принцип работы innerText'а.
Вот правильное решение:
if (document.documentElement.textContent === undefined) {
Object.defineProperty(HTMLElement.prototype, "textContent", {
get: function() {
return this.innerText;
},
set: function(value) {
this.innerText = value;
}
});
}
Но меня не столько интересует верный ответ, сколько то, почему вот этот код:
if (HTMLElement.prototype.textContent === undefined) {
HTMLElement.prototype.textContent = HTMLElement.prototype.innerText;
}
... не сработает.
Меня интересует:
Кто знает - объясните всю подноготную происходящего.
Спасибо.
Странно, почему решили стандартное свойство textContent
реализовывать через не стандартный стандартный с 2016 г. innerText
.
innerText
это свойство, в данном случае оно представлено в виде двух функции: getter и setter.
При обращении к свойству - происходит вычисление нужной функции, поэтому нельзя позаимствовать свойство целиком, как обычную функцию.
В этом случае
HTMLElement.prototype.innerText;
Происходит попытка получить значение innerText
, и так как HTMLElement.prototype
не является элементом, кидается исключение.
В правильном решении, добавляется новое свойство, внутри, которого вызывает уже имеющееся свойство, так как в момент вызова this
уже существующий элемент все работает.
Альтернативным решением может быть копирование определения свойства, для этого можно получить property descriptor
, с помощью Object.getOwnPropertyDescriptor
И затем добавить его же, но уже с нужным именем:
var innerTextPropertyDescriptor = Object.getOwnPropertyDescriptor(HTMLElement.prototype,'innerText');
Object.defineProperty(HTMLElement.prototype, "textContent", innerTextPropertyDescriptor);
Что находится внутри innerText'а? Точно такие же геттеры-сеттеры
Да.
почему операция присваивания, не делает из .textContent'а - обычную ссылку на тот объект?
Потому что при присваивании для левой части вызывается сеттер (или создаётся свойство), а для правой - геттер. Соответственно, ты присваиваешь значение, возвращённое геттером, а не сам геттер.
Или проблема в контексте this'ов?
Нет.
Вот правильное решение
Нет.
textContent
- IE9+ и все остальные
innerText
- IE6+ и все кроме FF45-
defineProperty
- IE9+ (IE8 с оговорками) и все остальные
Получается, что даже в идеальном случае это решение покрывает единстыенный браузер IE8 (и то, надо это проверять, причём, желательно, в самом браузере, а не в эмуляции).
И это не говоря о том, что эти свойства не являются взаимозаменяемыми, из-за чего в jQuery не стали так делать. Вот, запусти это в хроме:
var div = document.querySelector("div")
console.log(JSON.stringify(div.textContent))
console.log(JSON.stringify(div.innerText))
<div>
<span>123</span>
<script>var any = {}</script>
</div>
Да, свойство innerText
имеет геттер (можно в этом убедится в консоли браузера), поэтому для вычисления результата, который нужно присвоить свойству textContent
, он будет вызван. Поскольку геттер вызывается при этом не как метод объекта, а просто функция, то значением this
внутри геттера будет undefined
. В реализации геттера по всей видимости (если я правильно понимаю, это зашито в движке браузера) присутствует проверка на этот случай и результатом будет ошибка TypeError: 'get innerText' called on an object that does not implement interface HTMLElement.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Недавно начала изучение redux и столкнулся с проблемой, не знаю как поставить дефолтное значениеВот пример кода:
Всем добра! Есть строка такого вида: return showWiki({w: 'wall290708618_2192'}, false, event);