Питання про асоціативність Javascript “Uncaught TypeError: object is not a function”


94

Код такий:

<body>
    <a href="javascript:;" id="test">hello</a>
</body>

<script type="text/javascript">
    document.getElementById("test").addEventListener("click", function () {
      test()
    }, false)
    function test() {
      var postTypes = new Array('hello', 'there')   
      (function() { alert('hello there') })()
    }
</script>

Це призведе до:

"Uncaught TypeError: об'єкт не є функцією"

Якщо я оберну анонімний виклик / виклик функції в інший набір дужок, він виконає попередження, але все одно видасть мені помилку. Якщо я поставив крапку з комою після визначення "var postTypes", то це буде повністю нормально.

Мене переконали, що для JavaScript не потрібні крапки з комою, тому я здогадуюсь, що існують якісь дивні правила асоціативності застосування функцій, яких я не до кінця розумію. Чому я отримую цю помилку?


Виглядає майже так, ніби ви намагаєтесь створити як анонімну функцію, так і статичну функцію і очікуєте її виконання як однієї. Що станеться, якщо видалити функцію ()
brumScouse

Відповіді:


87

JavaScript вимагає крапки з комою, просто інтерпретатор вставляє їх для вас при розривах рядків, де це можливо * .

На жаль, код

var a = new B(args)(stuff)()

не чинить , НЕ призводить до синтаксичну помилку, так що НЕ ;буде вставлено. (Прикладом, який можна запустити, є

var answer = new Function("x", "return x")(function(){return 42;})();

Щоб уникнути подібних сюрпризів, навчіть себе завжди закінчувати висловлювання ;.


* Це просто емпіричне правило і не завжди відповідає дійсності. Правило вставки набагато складніше. Ця сторінка блогу про вставку крапки з комою містить більше деталей.


13
Або: щоб уникнути подібних сюрпризів, навчіться писати чистий читабельний код (який завжди повинен застосовуватися) і знати загальні правила ASI ... насправді це нічим не відрізняється від того, як "знати", як працює закриття в JS.

18

Ваш код переживає випадок, коли процес автоматичного введення крапки з комою (ASI) не відбувається.

Ніколи не слід покладатися на ASI. Ви повинні використовувати крапки з комою, щоб правильно відокремити твердження:

var postTypes = new Array('hello', 'there'); // <--- Place a semicolon here!!

(function() { alert('hello there') })();

Ваш код насправді намагався викликати об’єкт масиву.


Один із способів виправити проблему, але я не можу відстати від Крокфорд-клубу.

1
@pst: Дозвольте мені перефразувати, я не в Crock's-клубі взагалі :)
Christian C. Salvado

У такому випадку я перепрошую за різкі слова :(

Мені справді сподобалась вікторина. ASI дійсно жахливо плутає з icky-кодом!

8

Я отримав подібну помилку, і мені зайняв деякий час, щоб зрозуміти, що в моєму випадку я назвав змінну масиву payInvoices, а функція також payInvoices. Це бентежило AngularJs. Після того, як я змінив назву на processPayments (), це нарешті запрацювало. Просто хотів поділитися цією помилкою та рішенням, оскільки мені знадобилось багато часу, щоб це зрозуміти.


Те саме, у мене була змінна з ім'ям alertі намагався викликати функцію попередження javascript, і вона сказала б, що "попередження - це не функція". Він намагався викликати alertзмінну замість фактичної функції
James111,

0

Спробуйте мати тіло функції перед викликом функції у вашому файлі JavaScript.


0

Я отримував цю саму помилку і витратив півтора дня, намагаючись знайти рішення. Відповідь Наомі підвела мене до потрібного мені рішення.

У моєму введенні (type = button) був атрибут name, ідентичний імені функції, що викликається подією onClick. Одного разу я змінив атрибут, nameвсе працювало.

<input type="button" name="clearEmployer" onClick="clearEmployer();">

змінено на:

<input type="button" name="clearEmployerBtn" onClick="clearEmployer();">

0

У мене є ця помилка під час компіляції та збірки TS за допомогою WebPack. Він компілюється export class AppRouterElement extends connect(store, LitElement){....}в let Sr = class extends (Object(wr.connect) (fn, vr)) {....}який здається неправильним з - за відсутності коми. При поєднанні з Rollup помилок не виникає.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.