Чому певні виклики функцій у JavaScript називають «незаконними викликами»?


96

Наприклад, якщо я це роблю:

var q = document.querySelectorAll;

q('body');

Я отримую помилку "Незаконне виклик" у Chrome. Я не можу придумати жодної причини, чому це потрібно. З одного боку, це не так з усіма функціями власного коду. Насправді я можу це зробити:

var o = Object; // which is a native code function

var x = new o();

І все працює просто чудово. Зокрема, я виявив цю проблему, маючи справу з документом та консоллю. Будь-які думки?




Відповіді:


157

Це тому, що ви втратили "контекст" функції.

Коли ви телефонуєте:

document.querySelectorAll()

контекст функції є document, і буде доступний, як thisза допомогою реалізації цього методу.

Коли ви просто дзвоните q, контексту більше немає - це "глобальний"window об'єкт.

Реалізація querySelectorAllнамагається використовувати, thisале це вже не елемент DOM, це Windowоб'єкт. Реалізація намагається викликати якийсь метод елемента DOM, який не існує на Windowоб'єкті, і інтерпретатор не дивно називає фолом.

Щоб вирішити цю проблему, використовуйте .bindв новіших версіях Javascript:

var q = document.querySelectorAll.bind(document);

що забезпечить, щоб усі подальші виклики qмали правильний контекст. Якщо у вас немає .bind, скористайтеся цим:

function q() {
    return document.querySelectorAll.apply(document, arguments);
}

3
О, гарний дзвінок. Ви маєте рацію, тому що я можу зробити: q.apply (документ, ['тіло']); і це працює.
user1152187

Зауважте, що це не вимагає роботи для вбудованих функцій в IE. Наприклад, console.log не має там методу apply.
hugomg

@Alnitak: Так, це працює скрізь, крім IE, і тому вам часто слід просто передавати аргументи нормально, як у function q(x){ return document.querySelectorAll(x); }. Ще одна річ, яка мені дуже подобається в об’єктах браузера IE, полягає в тому, що деякі з них видають виняток, просто якщо ви намагаєтесь прочитати з них властивість, тому вам потрібно протестувати функції if( 'funcname' in browserobject)замість звичних if(browserobject.funcname)!
hugomg

Відмінна відповідь, мене справді спантеличило це явище, така сама ситуація, як і ОП.
тимчасове_користувацьке

1
Розум підірваний. Дякую.
rb-

1

У моєму випадку незаконний виклик стався через передачу незадекларованої змінної для функціонування в якості аргументу. Не забудьте оголосити змінну перед передачею функції.


оголошення змінної не матиме сенсу в даному конкретному випадку, оскільки незаконне виклик відбувається, оскільки метод, залежний від dom, викликається поза контекстом DOM, оскільки в той момент, коли ви робите q = document.something somethingметод втрачає контекст документа
Anshul Sahni


0

Ще одне коротке рішення:

const q=s=>document.querySelectorAll(s);
q('body');
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.