Зарезервированные имена функций в JavaScript - PullRequest
0 голосов
/ 02 октября 2018

После переименования моей функции код перестал работать.Это новое имя scrollIntoView, кажется, конфликтует с методом element.scrollIntoView().

<div onmousedown="scrollIntoView('id001')"/>

function scrollIntoView(id) {
    alert(id);
}

Я создал простой тестовый пример https://jsfiddle.net/mgtn215y/, который показал мойфункция просто игнорируется в пользу element.scrollIntoView() даже

  • она не вызывается для элемента
  • атрибуты не совпадают

Решение очевидно -использовать другое имя функции.Поскольку это поведение одинаково во всех основных браузерах, я ожидаю, что это где-то указано.Однако я не смог найти ничего, связанного, например, с лексической грамматикой JavaScript .Есть ли предпосылки для такого поведения?

Ответы [ 3 ]

0 голосов
/ 02 октября 2018

По какой-то странной причине похоже, что встроенные обработчики неявно используют with(this) при запуске, где this ссылается на элемент, вызвавший событие.Всякий раз, когда вы пытаетесь сослаться на что-то, если это что-то существует как свойство this, тогда будет ссылаться на это свойство , а не на внешнюю переменную с тем же именем:

console.log(typeof className); // Undefined in standard global scope
console.log(typeof scrollIntoView); // Undefined in standard global scope
.mydiv {
  width: 100px;
  height: 100px;
  background-color: red;
  cursor: pointer;
}
<div class="mydiv" onclick="
  console.log(typeof className); // Defined inside inline handler
  console.log(typeof scrollIntoView); // Defined inside inline handler
">

Для переводчика onclick на самом деле выглядит примерно так:

onclick="with(this) {
  console.log(typeof className);
  console.log(typeof scrollIntoView);
}"

Это довольно странно.Но встроенные обработчики событий в любом случае являются ужасной практикой и, вероятно, не должны использоваться;назначьте обработчик правильно с помощью addEventListener или onkeydown вместо:

document.querySelector('.mydiv').onmousedown = () => scrollIntoView("id001");
function scrollIntoView(id) {
  console.log(id);
}
.mydiv {
  width: 100px;
  height: 100px;
  background-color: red;
  cursor: pointer;
}
    <div class="mydiv"></div>
0 голосов
/ 02 октября 2018

Проблема заключается в цепочке областей действия функций, скомпилированных из значений атрибутов элемента HTML, объявленных в источнике HTML.Атрибуты формы on_eventName=functionBodyCode демонстрируют это поведение.

По историческим причинам (DOM не существовало в его нынешнем виде, document.getElementByID еще не было изобретено ...), такие функции компилируются с областью видимостицепь, содержащая объект, для которого предоставляется атрибут обработчика события, любой элемент form, в котором находится элемент, и объект document. Однако разные браузеры использовали разные подходы при эмуляции поведения Netscape.Некоторые браузеры включали любой родительский объект элемента, предоставляющего атрибут обработчика события, в то время как другие опускали некоторые подходящие объекты, такие как document.

Технические подробности можно найти в «Javascript the Definition Guide» O'Reilly, раздел «19.1.6. Область действия обработчиков событий».

Основная рекомендация - избегать предоставления обработчиков событий в HTML - добавьте их в JavaScript, используя вместо этого addEventListener.Если по какой-либо причине вызовы функций должны быть закодированы в значениях атрибутов HTML, не используйте имена функций, которые являются методами объектов DOM.

Обратите внимание, что цепочка пользовательских областей действия для обработчиков событий применяется только к функциям, созданным из атрибутов HTML. не применяется к функциям, созданным в JavaScript и добавленным к элементу с помощью addEventListener или element.onEventName=aFunctionObject.


В следующем фрагменте показано расположение имен свойств внешних элементов в цепочке областей действия обработчиков событий, определенных в HTML::

<form name="formName1" action="">
<p> Try to access the elements collection of the form:
   <button type="button"
      onclick="console.log( elements);">elements
   </button>
</p>

</form>
<form name="formName2" action="" onsubmit="return false">
<p> Try to access form name as form.name:
  <button type="button"
     onclick="console.log( 'form.name: %s', form.name);">form.name
  </button>
</p>
</form>

<form name="formName3" action="" onsubmit="return false">
<p>Access document.write as "write"
   <button type="button"
      onclick="console.log( 'write: %s', write);">write
   </button>
</p>
</form>
  • В первой форме elements является свойством окружающего элемента формы.

  • Во второй форме form является свойством HTMLButtonElement.

  • В третьей форме write является методом document.

0 голосов
/ 02 октября 2018

Чтобы переопределить, просто попробуйте:

Element.prototype.scrollIntoView = function(id) {
    alert(id);
}

Но учтите, что он работает с addEventListener:

var element = document.getElementById("element");

function scrollIntoView(id) {
    alert(id);
}

element.addEventListener("mousedown", function() {
    scrollIntoView("id001");
});
div {
  width: 100px;
  height: 100px;
  background-color: red;
  cursor: pointer;
}
<div id="element"></div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...