Подтвердить что ты не робот

Есть ли способ доказательства в будущем для добавления свойств в собственные объекты браузера с учетом поведения "строгого" поведения?

Недавно я заметил, что когда режим "use strict"; включен в браузерах, многие свойства на нативных объектах становятся неурегулированными.

Например

function() {
  "use strict";
  var div = document.createElement("div");
  div.offsetLeft = 0;  
}();

Игнорируйте тот факт, что установка offsetLeft глупа. Это не главное.

Если вы запустите это в Chrome или Firefox, вы получите сообщение об ошибке

Uncaught TypeError: Cannot set property offsetLeft of #<HTMLElement> which has only
a getter(…)

Удалите "use strict";, и ошибка исчезнет.

Итак, вот проблема. Позвольте изменить offsetLeft на то, что я могу использовать в своем собственном коде

function createElementAndAssociateData(data) {
  "use strict";
  var div = document.createElement("div");
  div.userdata = data;  
};

Это отлично работает, за исключением 2 лет с новой спецификации HTML5 и решает, что для всех HTMLElements атрибут userdata доступен только для чтения. Внезапно мой код разбивается везде, где я использовал "use strict";.

Ожидается ли это бомба замедленного действия, поскольку все больше и больше свойств добавляются к собственным объектам HTML5?

Существует ли безопасный способ использования "use strict"; и добавления пользовательских свойств к собственным объектам HTML5 или добавление какого-либо свойства к собственному объекту браузера никогда не будет выполнено?

Примечание. Я не считаю, что устранение имен свойств является приемлемым решением. Конечно, я мог бы изменить userdata на mycompanyname_myappname_userdata, но такой вид рядом с точкой. Есть ли какое-то другое решение или добавляет пользовательские свойства к собственным объектам HTML5 в строгом режиме анти-шаблон?

4b9b3361

Ответ 1

Да: символы ES6

Проблема со свойствами заключается в том, что их имя является строкой. Затем два разных кода могут использовать одно и то же имя для разных целей, и результат может быть катастрофическим.

Чтобы решить эту проблему, ECMAScript 6 вводит новый тип: Symbol.

Вы можете использовать его следующим образом:

var s1 = Symbol("My property");
object[s1] = "Some data 1";
object[s1]; // "Some data 1"

Тогда, даже если какой-либо другой код решит использовать символ с тем же описанием, столкновения не будет:

var s2 = Symbol("My property"); // Same description :S
object[s2] = "Some data 2";
object[s2]; // "Some data 2"
object[s1]; // "Some data 1" -- No problem :)

Ответ 2

Предполагаемый способ добавления пользовательских свойств - HTMLElement.dataset.

var div = document.createElement("div");
div.dataset.yourCustomProperty = 'some data';
div; // <div data-your-custom-property="some data">
div.dataset.yourCustomProperty; // "some data"

Это отражает пользовательские атрибуты data-*.

Обратите внимание, что .dataset.camelCase отражает data-camel-case и наоборот.

Ответ 3

В общем, ваш код также сломается, если вы удалите "use strict";, потому что ваше свойство не имеет значения, которое вы хотели бы иметь.

В общем, расширение родных объектов - не очень хорошая идея.

Вот несколько вариантов:

  • Используйте один разнесенный по имени ключ, например _myframeworkElemID, который не будет указан.

  • Создайте динамический ключ (аналогично 1.): Например, jQuery создает такой ключ: $.expando = 'jQuery' + Date.now();

  • Используйте jQuery.data или реализуйте аналогичное решение.

  • современные способы

    a) Символы (см. этот ответ)

    b) WeakMap:

window.elementData = new WeakMap();

//later than
//set data
elementData.set(element, data)

//get data
elementData.get(element);

Все это сказало. С моей точки зрения в настоящее время лучший способ сделать это выглядит следующим образом:

var expando = window.Symbol && Symbol() || '_myId' + Date.now();

//set data
element[expando] = data;

//get data
var data = element[expando];

Таким образом, вы используете функцию ES6 Symbol в браузерах, которые ее поддерживают, а в старых браузерах вы получаете уникальную строку, которая никогда не будет указана.

Вы также можете написать помощника, который возвращает символ.