Ошибка uncaught typeerror

Время на прочтение
5 мин

Количество просмотров 397K

JavaScript может быть кошмаром при отладке: некоторые ошибки, которые он выдает, могут быть очень трудны для понимания с первого взгляда, и выдаваемые номера строк также не всегда полезны. Разве не было бы полезно иметь список, глядя на который, можно понять смысл ошибок и как исправить их? Вот он!

Ниже представлен список странных ошибок в JavaScript. Разные браузеры могут выдавать разные сообщения об одинаковых ошибках, поэтому приведено несколько примеров там, где возможно.

Как читать ошибки?

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

Типичная ошибка из Chrome выглядит так:

Uncaught TypeError: undefined is not a function

Структура ошибки следующая:

  1. Uncaught TypeError: эта часть сообщения обычно не особо полезна. Uncaught значит, что ошибка не была перехвачена в catch, а TypeError — это название ошибки.
  2. undefined is not a function: это та самая часть про ошибку. В случае с сообщениями об ошибках, читать их нужно прямо буквально. Например, в этом случае, она значит то, что код попытался использовать значение undefined как функцию.

Другие webkit-браузеры, такие как Safari, выдают ошибки примерно в таком же формате, как и Chrome. Ошибки из Firefox похожи, но не всегда включают в себя первую часть, и последние версии Internet Explorer также выдают более простые ошибки, но в этом случае проще — не всегда значит лучше.

Теперь к самим ошибкам.

Uncaught TypeError: undefined is not a function

Связанные ошибки: number is not a function, object is not a function, string is not a function, Unhandled Error: ‘foo’ is not a function, Function Expected

Возникает при попытке вызова значения как функции, когда значение функцией не является. Например:

var foo = undefined;
foo();

Эта ошибка обычно возникает, если вы пытаетесь вызвать функцию для объекта, но опечатались в названии.

var x = document.getElementByID('foo');

Несуществующие свойства объекта по-умолчанию имеют значение undefined, что приводит к этой ошибке.

Другие вариации, такие как “number is not a function” возникают при попытке вызвать число, как будто оно является функцией.

Как исправить ошибку: убедитесь в корректности имени функции. Для этой ошибки, номер строки обычно указывает в правильное место.

Uncaught ReferenceError: Invalid left-hand side in assignment

Связанные ошибки: Uncaught exception: ReferenceError: Cannot assign to ‘functionCall()’, Uncaught exception: ReferenceError: Cannot assign to ‘this’

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

Наиболее частый пример этой ошибки — это условие в if:

if(doSomething() = 'somevalue')

В этом примере программист случайно использовал один знак равенства вместо двух. Выражение “left-hand side in assignment” относится к левой части знака равенства, а, как можно видеть в данном примере, левая часть содержит что-то, чему нельзя присвоить значение, что и приводит к ошибке.

Как исправить ошибку: убедитесь, что вы не пытаетесь присвоить значение результату функции или ключевому слову this.

Uncaught TypeError: Converting circular structure to JSON

Связанные ошибки: Uncaught exception: TypeError: JSON.stringify: Not an acyclic Object, TypeError: cyclic object value, Circular reference in value argument not supported

Всегда вызвано циклической ссылкой в объекте, которая потом передается в JSON.stringify.

var a = { };
var b = { a: a };
a.b = b;
JSON.stringify(a);

Так как a и b в примере выше имеют ссылки друг на друга, результирующий объект не может быть приведен к JSON.

Как исправить ошибку: удалите циклические ссылки, как в примере выше, из всех объектов, которые вы хотите сконвертировать в JSON.

Unexpected token ;

Связанные ошибки: Expected ), missing ) after argument list

Интерпретатор JavaScript что-то ожидал, но не обнаружил там этого. Обычно вызвано пропущенными фигурными, круглыми или квадратными скобками.

Токен в данной ошибке может быть разным — может быть написано “Unexpected token ]”, “Expected {” или что-то еще.

Как исправить ошибку: иногда номер строки не указывает на правильное местоположение, что затрудняет исправление ошибки.

Ошибка с [ ] { } ( ) обычно вызвано несовпадающей парой. Проверьте, все ли ваши скобки имеют закрывающую пару. В этом случае, номер строки обычно указывает на что-то другое, а не на проблемный символ.

Unexpected / связано с регулярными выражениями. Номер строки для данного случая обычно правильный.

Unexpected; обычно вызвано символом; внутри литерала объекта или массива, или списка аргументов вызова функции. Номер строки обычно также будет верным для данного случая.

Uncaught SyntaxError: Unexpected token ILLEGAL

Связанные ошибки: Unterminated String Literal, Invalid Line Terminator

В строковом литерале пропущена закрывающая кавычка.

Как исправить ошибку: убедитесь, что все строки имеют правильные закрывающие кавычки.

Uncaught TypeError: Cannot read property ‘foo’ of null, Uncaught TypeError: Cannot read property ‘foo’ of undefined

Связанные ошибки: TypeError: someVal is null, Unable to get property ‘foo’ of undefined or null reference

Попытка прочитать null или undefined так, как будто это объект. Например:

var someVal = null;
console.log(someVal.foo);

Как исправить ошибку: обычно вызвано опечатками. Проверьте, все ли переменные, использованные рядом со строкой, указывающей на ошибку, правильно названы.

Uncaught TypeError: Cannot set property ‘foo’ of null, Uncaught TypeError: Cannot set property ‘foo’ of undefined

Связанные ошибки: TypeError: someVal is undefined, Unable to set property ‘foo’ of undefined or null reference

Попытка записать null или undefined так, как будто это объект. Например:

var someVal = null;
someVal.foo = 1;

Как исправить ошибку: это тоже обычно вызвано ошибками. Проверьте имена переменных рядом со строкой, указывающей на ошибку.

Uncaught RangeError: Maximum call stack size exceeded

Связанные ошибки: Uncaught exception: RangeError: Maximum recursion depth exceeded, too much recursion, Stack overflow

Обычно вызвано неправильно программной логикой, что приводит к бесконечному вызову рекурсивной функции.

Как исправить ошибку: проверьте рекурсивные функции на ошибки, которые могут вынудить их делать рекурсивные вызовы вечно.

Uncaught URIError: URI malformed

Связанные ошибки: URIError: malformed URI sequence

Вызвано некорректным вызовом decodeURIComponent.

Как исправить ошибку: убедитесь, что вызовы decodeURIComponent на строке ошибки получают корректные входные данные.

XMLHttpRequest cannot load some/url. No ‘Access-Control-Allow-Origin’ header is present on the requested resource

Связанные ошибки: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at some/url

Эта проблема всегда связана с использованием XMLHttpRequest.

Как исправить ошибку: убедитесь в корректности запрашиваемого URL и в том, что он удовлетворяет same-origin policy. Хороший способ найти проблемный код — посмотреть на URL в сообщении ошибки и найти его в своём коде.

InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable

Связанные ошибки: InvalidStateError, DOMException code 11

Означает то, что код вызвал функцию, которую нельзя было вызывать в текущем состоянии. Обычно связано c XMLHttpRequest при попытке вызвать на нём функции до его готовности.

var xhr = new XMLHttpRequest();
xhr.setRequestHeader('Some-Header', 'val');

В данном случае вы получите ошибку потому, что функция setRequestHeader может быть вызвана только после вызова xhr.open.

Как исправить ошибку: посмотрите на код в строке, указывающей на ошибку, и убедитесь, что он вызывается в правильный момент или добавляет нужные вызовы до этого (как с xhr.open).

Заключение

JavaScript содержит в себе одни из самых бесполезных ошибок, которые я когда-либо видел, за исключением печально известной Expected T_PAAMAYIM_NEKUDOTAYIM в PHP. Большая ознакомленность с ошибками привносит больше ясности. Современные браузеры тоже помогают, так как больше не выдают абсолютно бесполезные ошибки, как это было раньше.

Какие самые непонятные ошибки вы встречали? Делитесь своими наблюдениями в комментариях.

P.S. Этот перевод можно улучшить, отправив PR здесь.

Рассматривать будем на примере данного объекта

const data = {
    name: 'TypeError',
    message: '',
    errors: null,
    sayHi: function() {
        console.log(this.name)
    }
}

Uncaught TypeError: *** is not a function

Данная ошибка возникает в том случае, когда у объекта мы пытаемся вызвать метод(функцию), но она таковой не является.

data.getName(); // <- Uncaught TypeError: data.getName is not a function
data.errors(); // <- Uncaught TypeError: data.errors is not a function

В первом случае getName() нет в объекте, во втором, errors не является функцией.

Несоответствие типов

Возможно, мы ожидаем, что к нам придет массив и мы пытаемся выполнить:

data.name.forEach(item => console.log(item));

Получим ошибку, так как у строк нет метода forEach

Ошибка экспорта/импорта зависимостей

// Экспорт из файла
const fnc = (a) => { return a*a; }
export { func: fnc() }
// Импорт
import { func } from 'module';
func(); // <- func is not a function

Мы ожидали, что будет импортирована функция, однако вместо самой функции, мы импортировали результат ее выполнения. Функции должны экспортироваться без вызова ()

Как избежать подобных ошибок?

Проверять, что приходит в объекте и существуют ли в объекте нужные нам данные. Один из вариантов проверки, воспользоваться console.log().
Можно начать с последнего ключа, однако лучше вывести весь пусть, чтобы понимать структуру, с которой работаем:

console.log(data) // { name: 'TypeError', message: '', errors: null, sayHi: [Function] }
console.log(data.errors) // null
console.log(data.sayHi) // [Function: sayHi]

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

// data существует, есть ключ sayHi и sayHi функция
if (data && data.sayHi && typeof data.sayHi === 'function') {
    data.sayHi();
}

При проверке в if лучше указывать полную цепочку ключей для проверки, так как, например, следующая конструкция вызовет исключение, т.к. data.values не существует:

if (data.values.showValue && typeof data.values.showValue === 'function') {
    console.log(data.values.showValue());
}

Сократить код можно, воспользовавшись оператором необязательной цепочки вызовов ‘?.‘:

// data существует?, есть ключ sayHi и sayHi функция
if (data?.sayHi && typeof data.sayHi === 'function') {
    data.sayHi();
}

Оператор необязательной цепочки вызовов будет проверять значение слева. Если значение null или undefined, цепочка прерывается и возвращается значение undefined.

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

if (data && data.sayHi && typeof data.sayHi === 'function') {
    data.sayHI(); // sayHI нет, но есть sayHi
}

Импорт/экспорт функций

При экспорте функций, передается только имя функции.

// Экспорт из файла
const fnc = (a) => { return a*a; }
export { func: fnc } // Нет ()
// Импорт
import { func } from 'module';
func(2); // <- 4

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

function counterFnc() {
  let count = 0;
  return () => {
    return ++count;
  }
}

class Counter {
  #count = 0;
  inc() {
    return ++this.#count;
  }
}
const incer = new Counter();
export { 
  counter: counterFnc(),
  countCl: incer,
  increase: incer.inc
}
// import
import { counter, countCl, increase } from 'module';
counter(); // OK
countCl.inc(); // OK
increase(); // OK

JavaScript (JS) is the most popular programming language and is ranked as one of the TOP 5 programming languages in the world. TypeScript is JavaScript with type syntax and is a strongly typed programming language based on JS that provides better tooling at any size. But, internally, it’s again JavaScript. Today almost everyone uses JavaScript for front-end web development, and frameworks such as React, Vue, and Angular made JavaScript even more popular.

Before getting in to the article to understand Uncaught TypeError in Javascript, one should understand basics about Javascript, lets go through it below.

Table Of Contents

  • 1 What is JavaScript?
    • 1.1 Why do we need JavaScript?
    • 1.2 Advantages of JavaScript
    • 1.3 Disadvantages of JavaScript
    • 1.4 JavaScript Error Types
  • 2 What is Uncaught TypeError?
    • 2.1 The TypeError: Cannot read property of undefined 
  • 3 What Causes Uncaught TypeError?
    • 3.1 Causes for TypeError: Cannot Read Property of Undefined
  • 4 How to Fix Uncaught TypeError?
    • 4.1 The solution to TypeError: Cannot read properties of undefined 
  • 5 Guidelines to Avoid the Errors in JavaScript

What is JavaScript?

JavaScript is a lightweight, interpreted, and all-in-one compiled programming language with first-class functions. It is used chiefly as the scripting language for web pages. Earlier, it was restricted to only client-side scripting with NodeJS. Now, JavaScript is used for both front-end and back-end development of web applications. Since then, it has grown alongside new browsers such as Mozilla Firefox and Google Chrome. The latter even began creating V8, the first contemporary JavaScript engine that translates bytecode into native machine code.

Know More: Comparisons of Top 3 Javascript testing frameworks

Why do we need JavaScript?

JavaScript allows handling complex features of a webpage dynamically. The webpage typically contains three different parts; namely:

HTML: A markup language that provides the structure of a webpage or contents of a webpage. Such as header, footer, images, table, etc.

CSS: Also known as Cascading Style Sheets, CSS is used to style your webpage contents. Such as font, background color, and foreground color. The CSS also provides animations.

JavaScript: An essential part of any webpages, JavaScript can help you dynamically create and update the contents, handle the events, control multimedia, etc.

Advantages of JavaScript

Speed: The JavaScript application is much faster than any application not written in JavaScript.

Scripting Language: JavaScript is a powerful scripting language for web applications. It has become a core of web applications. JS supports both Client-side scripting and service-side scripting.

Interpreter Based: JavaScript doesn’t need any compiler. It is interpreter based. When you run the JS in the browser, the browser engine interprets and executes the JavaScript line by line. Unlike the compiled language like Java, C#, and C++, the code must be compiled first before executing it, but JavaScript doesn’t require it to be compiled.

Event Handling: The event is an action in a system that needs to be handled/responded to. For example, a click is an event: when the user clicks on the button, the click event is triggered and responded to with an alert box. JavaScript can handle such events efficiently and allows you to create custom events.

Control Statements: JavaScript provides the control statements like if-else, switch, etc. It also provides the loop statement such as while, for, and for-each. This helps to write complex logic.

Higher Order Functions: The function that returns a function is called a higher-order function, and JS supports higher-order functions.

Dynamic Typing: One of the essential features of JavaScript. The declaration of a variable is optional. JavaScript doesn’t require the declaration of the variable during the assignment of value. JS determines the type of the value and creates the variable accordingly. That means no need to specify the string, integer, etc. explicitly.

Async Function: JavaScript supports async functions. The async and await keywords enable the asynchronous, promise-based behavior to be written in a clear style—no need to configure the promised change explicitly.

Versatility: JavaScript can be used for both front-end and back-end web development.

Disadvantages of JavaScript

Client-side Security: JavaScript is viewable to the user; some may use it for malicious purposes. It’s easy to identify the application flaws (if any) and inject the malicious code.

Browser Compatibility: The JavaScript code interpretation varies from browser to browser. The code must be thoroughly tested. The older version of the browser might not support some new functionalities. There are also chances that the more recent browser version might lack the support for older functionalities due to security or any reason.

Debugging: Though there are many debugging tools, the console is still the favorite debugging tool for JavaScript. The debugging is considerably tricky compared with other languages.

JavaScript Error Types

JavaScript has the standard built-in objects, a predefined set of objects that helps to develop faster. Undefined is the most error-prone of the six primitive types defined in JavaScript: Boolean, String, Symbol, BigInt, Null, and Undefined.

The problem frequently occurs when the scripts encounter an uninitialized variable or object.

As we are discussing the Error Uncaught TypeError: Cannot read property of undefined, let’s understand the JavaScript built-in error first, then jump to the TypeError.

Error objects are thrown during the runtime errors. This object can also be used as a base object for user-defined exceptions. There are many built-in error objects in JavaScript other than Generic Error.

RangeError

The RangeError object is an error thrown when a value is not in the set or range of allowed values.

Common Scenarios:

  • When you try to create an array of illegal lengths using the Array Constructor
  • Passing non-allowed values to numeric methods such as toExponential(), toPrecision(), and toFixed()
  • Passing non-allowed values to string functions like normalize()

ReferenceError

The Reference Error object indicates an error when a variable that doesn’t exist (or hasn’t yet been initialized) in the current scope is referenced.

Example Error Message: ReferenceError: assignment to the undeclared variable “s”

Common Scenarios:

  • Typo in the variable name
  • When you try to access the variable outside their scopes
  • Referencing a global variable from an external library before it is loaded

SyntaxError

The Syntax Error object indicates an error when trying to interpret syntactically invalid code. It is thrown when the JavaScript engine encounters token or token order that does not conform to the syntax of the language.

Example: Uncaught SyntaxError: Invalid or unexpected token

Common Scenarios:

  • Missing inverted commas
  • Missing Parenthesis, braces
  • Illegal usage of special characters

TypeError

The TypeError occurs when a variable or parameter is not of a valid type.

Common Scenarios:

  • Invoking objects that are not methods
  • Attempting to access properties of null or undefined objects
  • Treating a number as a string or vice versa

Few other common Error Type in JavaScript includes

URIError: The URIError indicates that the global URI handling function was used in the wrong way.

AggregateError: The Aggregate Error is an error when several errors are wrapped into a single error. The aggregate error is useful when multiple errors need to be reported by an operation.

JavaScript is the most flexible language; besides the standard set of Error Types, it also allows custom errors. You can always create a new error type in JavaScript if your requirement is not in the standard error list. Now lets understand about Uncaught TypeError below,

What is Uncaught TypeError?

The TypeError: Cannot read property of undefined 

The most common Error in JavaScript is TypeError: Cannot read property of undefined. The “TypeError: Cannot read property of undefined” belongs to the TypeError category in JavaScript. Usually, you get the error message something similar to below

TypeError: Cannot read properties of undefined (reading x)

What Causes Uncaught TypeError?

Causes for TypeError: Cannot Read Property of Undefined

The error clearly says that it is Undefined, which means the variable might be declared or used. Still, there is no value associated with the variable. In short, the value is not assigned.

In JavaScript, properties or functions are Objects, but undefined is not an object type. If you call the function or property on such variable, you get the error in console TypeError: Cannot read undefined properties.

Example of Type Error

Let’s understand the TypeError: Cannot read property of undefined

Errors are a core part of learning and using any programming language. Error messages tend to help you understand what has gone wrong somewhere in your code.

While some error messages are straightforward and easy to understand, some might be a bit confusing when you see them.While errors make coding so frustrating, they can also help you master whatever programming language you use. 🧑🏻‍💻 Find out how to fix one of the most common JavaScript errors in this guide ⬇️Click to Tweet

In this tutorial, we’ll talk about one of the most common JavaScript errors — the “uncaught typeerror: cannot read property” error.

At the end of this tutorial, you should understand what the “uncaught typeerror: cannot read property” means, the common causes, and how to fix them.

What Does “uncaught typeerror: cannot read property” Mean in JavaScript?

The “uncaught typeerror: cannot read property” error mainly occurs when you try to use or access an undefined variable. This error can be raised when you’re using vanilla JavaScript or any Javascript framework.

You can easily detect errors while coding by using various developer tools like the Chrome dev tools, and the Kinsta one-click staging tool to intercept errors, test your code, and more.

How To Fix the “uncaught typeerror: cannot read property” Error in JavaScript

In the sections that follow, we’ll highlight some of the causes of the “uncaught typeerror: cannot read property” error and how to fix them using code examples.

Accessing an Object Property With a Value of Undefined

In this section, we’ll discuss one of the possible causes of the “uncaught typeerror: cannot read property” error in JavaScript. This has to do with accessing an object property that is yet to be undefined.

Here’s an example:

let person;

In the code above, we created a variable called person. The intention is to make this variable an object with properties like name, age, hobby.

Assuming you forget to create these properties, you’ll get an error when you try to access them. That is:

let person;
console.log(person.name);
// Uncaught TypeError: Cannot read properties of undefined (reading 'name')

As can be seen above, we tried accessing the name property which doesn’t exist so we got an error saying: Uncaught TypeError: Cannot read properties of undefined (reading ‘name’).

This can happen to anyone as you may forget to create/add properties to your object.

Let’s go on and add some properties to the object to fix the error:

let person = {
  name: "John",
  age: 200,
  hobby: "coding"
}
console.log(person.name);
// John

In the code above, we’ve added the name property so when you try to access it, you’ll get the value of “John” returned.

Accessing an Element That Doesn’t Exist in an Array

Just like we saw in the last section with objects, you’d also get the “uncaught typeerror: cannot read property” error raised if you try to access an element in an array that is yet to be initialized.

Here’s an example:

let arr;
console.log(arr[0]);
// Uncaught TypeError: Cannot read properties of undefined (reading '0')

In the example above, we tried accessing the first element of an array called arr.

The array has been declared but not initialized — this means that no element has been assigned to it yet.

To fix this, we’ll add elements to the array before accessing them. That is:

let arr = [2,4,6,8]
console.log(arr[0]);
// 2

Accessing a DOM Element That Doesn’t Exist

When working with the Document Object Model (DOM) in JavaScript, you might encounter the “uncaught typeerror: cannot read property”.

This can happen for different reasons like spelling errors while referencing the DOM element, accessing an element that doesn’t exist, or accessing an element before the DOM has been loaded (we’ll talk about this in the next section).

In this section, you’ll see an example that throws the “uncaught typeerror: cannot read property” error for accessing an inexistent DOM element.

Here’s the HTML code:

<!DOCTYPE html>
<html>
  <head>
    <title>Error Tutorial</title>
  </head>
  <body>
    <h1 id="content">Hello World!</h1>
    <script src="app.js"></script>
  </body>
</html>

In the code above, we created a basic HTML document with a h1 element with an ID of “content”.

Here’s the JavaScript code:

let content = document.getElementById("constent");
console.log(content.textContent);
// Uncaught TypeError: Cannot read properties of null (reading 'textContent');

The code above raises the “uncaught typeerror: cannot read property” error even though it looks like we did everything right.

It’s pretty easy to miss what’s raising this error. It is raised because we spelt “constent” instead of “content” while referencing the ID of the h1 element.

That is, document.getElementById("constent"); instead of document.getElementById("content");.

The same error will be raised if you try to reference an ID or class name that is yet to be created in the DOM.

To fix this, you can simply check for spelling errors or make sure the element being referenced actually exists in the DOM.

Placing the Script Element Above Other DOM Elements Within the Body Tag

The position of your script element determines how your JavaScript code is executed in the browser.

If you place the script element above every other element in the body of your HTML document, the JavaScript code will run before the DOM has been loaded.

This means that JavaScript will not have any reference to the DOM elements because it didn’t wait for them to be loaded before executing.

Here’s an example:

<!DOCTYPE html>
<html>
  <head>
    <title>Error Tutorial</title>
  </head>
  <body>
    <script src="app.js"></script>
    <h1 id="content">Hello World!</h1>
  </body>
</html>

In the code above, we placed the script element above the h1 element.

Here’s the JavaScript code where we try to make reference to the h1 element by using its ID:

let content = document.getElementById("content");
console.log(content.textContent);
// Uncaught TypeError: Cannot read properties of null (reading 'textContent');

As expected, the “uncaught typeerror: cannot read property” error was thrown at us because JavaScript code before the h1 element could be registered to the DOM.

To fix this problem, always put your script element before the closing body tag; that is, below every other DOM element in the body of the document. This way, the script will start running after every element in the DOM has been loaded.

<!DOCTYPE html>
<html>
  <head>
    <title>Error Tutorial</title>
  </head>
  <body>
    <h1 id="content">Hello World!</h1>
    <script src="app.js"></script>
  </body>
</html>

Summary

Errors are an unavoidable part of being a developer. While they might make you frustrated while coding, they can also help learn more and master whatever programming language you’re using.

When faced with an error, you should always try to understand the error message because it will help you know where to start and what to fix. You’ll also be able to fix other errors with similar error messages.Learn what the ‘uncaught typeerror: cannot read property’ means, the common causes, and how to fix them — all in this guide! 🛠Click to Tweet

If you’re going to build a website, there are a variety of skills to learn and a lot of practice required to use these skills efficiently. DevKinsta makes the process easier from design, development, and deployment all in your local machine. DevKinsta is used by over 25,000 developers, web designers, and freelancers. Check it out for free today.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

От автора: чтобы вернуть сообщество разработчиков, мы рассмотрели нашу базу данных по тысячам проектов и нашли 10 самых распространённых ошибок в JavaScript. Мы собираемся показать вам, что к ним приводит и как это предотвратить. Если ни одна ошибка JavaScript не встречается в вашем коде, это делает вас лучшим разработчиком.

Поскольку всем управляют данные, мы собрали, проанализировали и оценили первые 10 ошибок JavaScript. Rollbar собирает все ошибки из каждого проекта и суммирует, сколько раз каждая из них возникала. Мы делаем это, группируя ошибки в соответствии с их отпечатками пальцев . В принципе, группируется по две ошибки, если вторая — это просто повторение первой. Это дает пользователям хороший обзор вместо огромной свалки, какую вы видели в файле журнала.

Мы сосредоточились на ошибках, которые скорее всего повлияют на вас и ваших пользователей. Чтобы сделать это, мы оценили ошибки по количеству проектов, испытывающихся в разных компаниях. Если бы мы посмотрели только на общее количество раз, когда произошла каждая ошибка, то клиенты большого объема могли бы подавить набор данных с ошибками, которые не имеют отношения к большинству читателей.

Вот первые 10 ошибок JavaScript:

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Профессия Frontend-разработчик PRO

Готовим Frontend-разработчиков с нуля

На курсе вы научитесь создавать интерфейсы веб-сервисов с помощью языков программирования и
дополнительных технологий. Сможете разрабатывать планировщики задач, мессенджеры, интернет-магазины…

Узнать подробнее

До 10 проектов в портфолио для старта карьеры

Подходит для новичков без опыта в программировании

Практика на вебинарах с разработчиками из крупных компаний

Ошибки были сокращены для удобства чтения. Давайте погрузимся глубже в каждую, чтобы определить, что может вызвать её, и как избежать их появления.

1. Uncaught TypeError: Cannot read property

Если вы разработчик JavaScript, то, вероятно, видели эту ошибку очень много раз. Это происходит в Chrome, когда вы читаете свойство или вызываете метод на неопределенный объект. Это можно очень легко проверить в консоли разработчика Chrome.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Это может произойти по многим причинам, но чаще всего это неправильная инициализация состояния при рендеринге компонентов пользовательского интерфейса. Давайте рассмотрим пример того, как это может произойти в реальном приложении. Мы выберем React, но те же принципы неправильной инициализации применимы и к Angular, Vue или любой другой структуре.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

class Quiz extends Component {

  componentWillMount() {

    axios.get(‘/thedata’).then(res => {

      this.setState({items: res.data});

    });

  }

  render() {

    return (

      <ul>

        {this.state.items.map(item =>

          <li key={item.id}>{item.name}</li>

        )}

      </ul>

    );

  }

}

Здесь понимаются две важные вещи:

Состояние компонента (например, this.state ) начинает жизнь как undefined.

Когда вы извлекаете данные асинхронно, компонент будет отображаться как минимум один раз перед загрузкой данных — независимо от того, выбрана ли она в конструкторе componentWillMount или componentDidMount . Когда Quiz отображается впервые, this.state.items не определен. Это, в свою очередь, означает, что ItemList получает элементы как неопределенные, и вы получаете сообщение об ошибке «Uncaught TypeError: Невозможно прочитать карту свойств» в консоли.

Это легко исправить. Самый простой способ: инициализировать состояние с разумными значениями по умолчанию в конструкторе.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

class Quiz extends Component {

  // Added this:

  constructor(props) {

    super(props);

    // Assign state itself, and a default value for items

    this.state = {

      items: []

    };

  }

  componentWillMount() {

    axios.get(‘/thedata’).then(res => {

      this.setState({items: res.data});

    });

  }

  render() {

    return (

      <ul>

        {this.state.items.map(item =>

          <li key={item.id}>{item.name}</li>

        )}

      </ul>

    );

  }

}

Код в вашем приложении может отличаться, но мы надеемся, что дали вам достаточно информации, чтобы исправить или избежать этой проблемы. Если нет, продолжайте читать, потому что далее мы рассмотрим больше примеров связанных с ошибками.

2. TypeError: ‘undefined’ is not an object (evaluating

Эта ошибка возникает в Safari при чтении свойства или вызове метода для неопределенного объекта. Вы можете проверить это в консоли разработчика Safari. Это по сути то же самое, что и вышеприведенная ошибка для Chrome, только Safari использует другое сообщение об ошибке.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

3. TypeError: null is not an object (evaluating

Это ошибка, которая возникает в Safari при чтении свойства или вызове метода для пустого объекта. Проверить это можно в консоли разработчика Safari.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Интересно, что в JavaScript значения null и undefined не совпадают, поэтому мы видим два разных сообщения об ошибках. Undefined обычно является переменной, которая не была назначена, а null означает, что значение пустое. Чтобы убедиться, что они не одно и то же, попробуйте использовать строгий оператор равенства:

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Один из способов, которым эта ошибка может возникнуть в реальном мире — это попытка использовать элемент DOM в JavaScript перед загрузкой элемента. Это потому, что DOM API возвращает null для ссылок на пустые объекты.

Любой JS-код, который выполняет и обрабатывает элементы DOM, должен выполняться после создания элементов DOM. JS-код интерпретируется сверху вниз, как изложено в HTML. Итак, если перед элементами DOM есть тег, код JS в теге скрипта будет выполняться, когда браузер анализирует HTML-страницу. Вы получите эту ошибку, если элементы DOM не были созданы до загрузки сценария.

В этом примере мы можем решить проблему, добавив прослушиватель событий, который уведомит нас, когда страница будет готова. После addEventListener метод init() может использовать элементы DOM.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

<script>

  function init() {

    var myButton = document.getElementById(«myButton»);

    var myTextfield = document.getElementById(«myTextfield»);

    myButton.onclick = function() {

      var userName = myTextfield.value;

    }

  }

  document.addEventListener(‘readystatechange’, function() {

    if (document.readyState === «complete») {

      init();

    }

  });

</script>

<form>

  <input type=«text» id=«myTextfield» placeholder=«Type your name» />

  <input type=«button» id=«myButton» value=«Go» />

</form>

4. (unknown): Script error

Ошибка скрипта возникает, когда ошибка неперехваченного JavaScript пересекает границы домена и нарушает политику перекрестного происхождения. Например, если вы размещаете свой код JavaScript на CDN, любые неперехваченные ошибки (ошибки, которые появляются в обработчике window.onerror, вместо того, чтобы быть пойманным в try-catch) будут переданы как просто «Script error» вместо того, чтобы содержать полезную информацию. Эта мера безопасности браузера предназначена для предотвращения передачи данных по доменам, которые в противном случае не были бы допущены к коммуникации.

Чтобы получить реальные сообщения об ошибках, выполните следующие действия:

1. Отправьте заголовок Access-Control-Allow-Origin

Установка заголовка Access-Control-Allow-Origin в * означает, что к ресурсу можно получить доступ из любого домена. Вы можете заменить * своим доменом, если необходимо: например, Access-Control-Allow-Origin: www.example.com . Если вы используете CDN из-за проблем с кэшированием, которые могут возникнуть, обработка нескольких доменов становится сложной и нельзя не приложить усилий. Подробнее см. здесь.

Вот несколько примеров того, как установить этот заголовок в различных средах:

Apache

В папках, где будут храниться ваши файлы JavaScript, создайте файл .htaccess со следующим содержимым:

Header add AccessControlAllowOrigin «*»

Nginx

Добавьте директиву add_header в блок местоположения, который служит файлам JavaScript:

location ~ ^/assets/ { add_header AccessControlAllowOrigin *; }

HAProxy

Добавьте в ресурс, где будут загружены файлы JavaScript:

rspadd AccessControlAllowOrigin: *

2. Установите crossorigin = «anonymous» в теге скрипта

В HTML-источнике для каждого из сценариев, где вы установите заголовок Access-Control-Allow-Origin, в теге SCRIPT установите crossorigin=»anonymous». Убедитесь, что заголовок отправляется для файла сценария, перед добавлением свойства crossorigin в тег скрипта. В Firefox, если атрибут crossorigin присутствует, но заголовок Access-Control-Allow-Origin отсутствует, сценарий не будет выполнен.

5. TypeError: Object doesn’t support property

Это ошибка, которая возникает в IE при вызове неопределенного метода. Вы можете проверить это в IE Developer Console.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Это эквивалентно ошибке «TypeError: ‘undefined’ is not a function» в Chrome. Да, разные браузеры могут иметь разные сообщения для одной и той же ошибки.

Это обычная проблема для IE в веб-приложениях, использующих пространство имен JavaScript. Когда это так, проблема в 99,9% случаев— это неспособность IE связать методы в текущем пространстве имен с ключевым словом this. Например, если у вас есть пространство имен имен Rollbar с помощью метода isAwesome. Обычно, если вы находитесь в пространстве имен Rollbar вы можете вызвать метод isAwesome со следующим синтаксисом:

Chrome, Firefox и Opera с радостью согласятся с этим синтаксисом. С другой стороны, IE не станет. Таким образом, самая безопасная ставка при использовании JS namespacing — это префикс с фактическим пространством имен.

6. TypeError: ‘undefined’ is not a function

Это ошибка, возникающая в Chrome при вызове неопределенной функции. Вы можете протестировать это в консоли разработчика Chrome и в Mozilla Firefox.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

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

Рассмотрим фрагмент кода:

function clearBoard(){

  alert(«Cleared»);

}

document.addEventListener(«click», function(){

  this.clearBoard(); // what is “this” ?

});

Выполнение вышеуказанного кода приводит к следующей ошибке: «Uncaught TypeError: undefined is not function». Причина, по которой вы получаете эту ошибку, заключается в том, что при вызове setTimeout() вы вызываете window.setTimeout(). В результате анонимная функция, передаваемая setTimeout(), определяется в контексте объекта окна, у которого нет clearBoard().

Традиционное решение, совместимое со старым браузером — просто сохранить ссылку на this в переменной, которая затем может быть унаследована закрытием. Например:

var self=this;  // save reference to ‘this’, while it’s still this!

document.addEventListener(«click», function(){

  self.clearBoard();

});

Кроме того, в новых браузерах для передачи правильной ссылки вы можете использовать метод bind():

document.addEventListener(«click»,this.clearBoard.bind(this));

7. Uncaught RangeError: Maximum call stack

Это ошибка, которая возникает в Chrome при нескольких обстоятельствах. Одно из них — когда вы вызываете рекурсивную функцию, которая не завершается. Вы можете протестировать это в консоли разработчика Chrome.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Это также может произойти, если вы передадите значение функции, находящейся за пределами допустимого диапазона. Многие функции принимают только определенный диапазон чисел для своих входных значений. Например, Number.toExponential(digits) и N umber.toFixed(digits) принимают цифры от 0 до 20, а Number.toPrecision(digits) принимают цифры от 1 до 21.

var a = new Array(4294967295);  //OK

var b = new Array(1); //range error

var num = 2.555555;

document.writeln(num.toExponential(4));  //OK

document.writeln(num.toExponential(2)); //range error!

num = 2.9999;

document.writeln(num.toFixed(2));   //OK

document.writeln(num.toFixed(25));  //range error!

num = 2.3456;

document.writeln(num.toPrecision(1));   //OK

document.writeln(num.toPrecision(22));  //range error!

8. TypeError: Cannot read property ‘length’

Это ошибка, которая возникает в Chrome из-за свойства длины чтения для неопределенной переменной. Вы можете протестировать это в консоли разработчика Chrome.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Обычно вы определяете длину, определенную в массиве, но вы можете столкнуться с этой ошибкой, если массив не инициализирован или если имя переменной скрыто в другом контексте. Давайте рассмотрим эту ошибку на следующем примере.

var testArray= [«Test»];

function testFunction(testArray) {

    for (var i = 0; i < testArray.length; i++) {

      console.log(testArray[i]);

    }

}

testFunction();

Когда вы объявляете функцию с параметрами, эти параметры становятся локальными. Это означает, что даже если у вас есть переменные с именами testArray , параметры с одинаковыми именами внутри функции будут по-прежнему рассматриваться как локальные.

У вас есть два способа решить эту проблему:

1. Удалите параметры в объявлении функции (оказывается, вы хотите получить доступ к тем переменным, которые объявлены вне функции, поэтому вам не нужны параметры для вашей функции):

var testArray = [«Test»];

/* Precondition: defined testArray outside of a function */

function testFunction(/* No params */) {

    for (var i = 0; i < testArray.length; i++) {

      console.log(testArray[i]);

    }

}

testFunction();

2. Вызовите функцию, передав ей массив, который мы объявили:

var testArray = [«Test»];

function testFunction(testArray) {

   for (var i = 0; i < testArray.length; i++) {

      console.log(testArray[i]);

    }

}

testFunction(testArray);

9. Uncaught TypeError: Cannot set property

Когда мы пытаемся получить доступ к неопределенной переменной, она всегда возвращает undefined, а мы не можем получить или установить любое свойство undefined. В этом случае приложение будет выбрасывать “Uncaught TypeError cannot set property of undefined.”

Например, в браузере Chrome:

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Если объект test не существует, будет выдаваться ошибка: “Uncaught TypeError cannot set property of undefined.”

10. ReferenceError: event is not defined

Эта ошибка возникает при попытке получить доступ к переменной, которая не определена или находится за пределами текущей области. Вы можете легко протестировать её в браузере Chrome.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Если вы получаете эту ошибку при использовании системы обработки событий, убедитесь, что вы используете объект события, переданный в качестве параметра. Старые браузеры, такие как IE, предлагают событие глобальной переменной, но не поддерживаются во всех браузерах. Библиотеки, подобные jQuery, пытаются нормализовать это поведение. Тем не менее, лучше использовать тот объект, который передается в функцию обработчика событий.

document.addEventListener(«mousemove», function (event) {

  console.log(event);

})

Вывод

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

Rollbar предлагает уникальные возможности для приложений JavaScript, таких как телеметрия, которые сообщают вам, что произошло в браузере пользователя, что приводит к ошибке. Это прозрение, которого у вас нет за пределами локальной консоли разработчика.

Автор: Jason Skowronski

Источник: //rollbar.com/

Профессия Frontend-разработчик PRO

Готовим Frontend-разработчиков с нуля

На курсе вы научитесь создавать интерфейсы веб-сервисов с помощью языков программирования и
дополнительных технологий. Сможете разрабатывать планировщики задач, мессенджеры, интернет-магазины…

Узнать подробнее

До 10 проектов в портфолио для старта карьеры

Подходит для новичков без опыта в программировании

Практика на вебинарах с разработчиками из крупных компаний

Редакция: Команда webformyself.

Понравилась статья? Поделить с друзьями:

Не пропустите эти материалы по теме:

  • Яндекс еда ошибка привязки карты
  • Ошибка uncaught referenceerror jquery is not defined
  • Ошибка unhandled exception has occurred in your application
  • Ошибка unmountable boot volume windows 10 как исправить
  • Ошибка unc synology

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии