оригинал:rollbar.com/blog/top-10…
Отказ от ответственности: исходный текст был немного изменен для удобства чтения.
предисловие
Просмотрев тысячи проектов, я нашел 10 самых распространенных ошибок в JavaScript. Мы расскажем вам, что вызывает эти ошибки и как их предотвратить. Если вы сможете избежать попадания в эти «ловушки», вы станете лучшим разработчиком.
10 самых распространенных ошибок в JavaScript:
Для удобства чтения мы сократили описание каждой ошибки. Далее давайте углубимся в каждую ошибку, чтобы определить, что ее вызывает и как ее избежать.
1. Uncaught TypeError: невозможно прочитать свойство
Если вы разработчик JavaScript, скорее всего, вы видели эту ошибку больше раз, чем осмелились признать. Эта ошибка возникает в Chrome, когда вы читаете свойство или вызываете метод неопределенного объекта. Вы можете легко протестировать его в консоли разработчика Chrome.
Это происходит по многим причинам, но наиболее распространенной из них является неправильная инициализация состояния при отрисовке компонентов пользовательского интерфейса.
Давайте рассмотрим пример, который происходит в реальном приложении: мы выбираем React, но то же самое относится и к Angular, Vue или любому другому фреймворку.
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
не определено.
Это легко исправить. Самый простой способ: инициализировать состояние в конструкторе.
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' не является объектом
Это ошибка при чтении свойства или вызове метода неопределенного объекта в Safari. Вы можете легко протестировать в консоли разработчика Safari. В основном это та же ошибка, что и в Chrome, упомянутая в пункте 1, но Safari использует другое сообщение об ошибке.
3. TypeError: null не является объектом
Это ошибка в Safari при чтении свойства или вызове метода для пустого объекта. Вы можете легко протестировать в консоли разработчика Safari.
Интересно, что в JavaScriptnull
а такжеundefined
Да и нет, поэтому мы видим два разных сообщения об ошибках.
undefined
обычно является переменной, которая еще не была присвоена, в то время какnull
Указывает, что значение пусто. Чтобы убедиться, что они не равны, попробуйте использовать оператор строгого равенства===
Один из сценариев, в котором эта ошибка может возникнуть в нашей работе, — это попытка использовать элемент в JavaScript до того, как этот элемент будет загружен. Потому что DOM API возвращает null для пустых ссылок на объекты.
Любой код JS, который выполняет и обрабатывает элементы DOM, должен выполняться после создания элемента DOM.
Код JS интерпретируется сверху вниз, как указано в HTML. Таким образом, если элементу DOM предшествует тег, код JS внутри тега script будет выполняться, когда браузер анализирует HTML-страницу. Эта ошибка возникает, если элемент DOM не был создан до загрузки скрипта.
В этом примере мы можем исправить это, добавив прослушиватель событий, который будет уведомлять нас, когда страница будет готова. однаждыaddEventListener
срабатывает,init()
способ работы с элементами DOM.
<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. (неизвестно): ошибка скрипта
Этот тип ошибки скрипта возникает, когда неперехваченные ошибки JavaScript (вызванные обработчиком window.onerror, а не перехваченные в try-catch) ограничены политикой браузера относительно разных источников. Например, если вы размещаете свой код JavaScript в CDN, любые неперехваченные ошибки будут отмечены как «ошибки сценария» вместо того, чтобы включать полезную информацию о стеке. Это мера безопасности браузера, предназначенная для предотвращения передачи данных между доменами, иначе обмен данными будет невозможен.
Чтобы получить настоящее сообщение об ошибке:
1. Установите заголовок «Access-Control-Allow-Origin».
Установка для заголовка Access-Control-Allow-Origin значения * означает, что доступ к ресурсу возможен корректно из любого домена.
Настройки в Nginx следующие:
Добавьте директиву add_header в блок местоположения, где обслуживаются файлы JavaScript:
location ~ ^/assets/ {
add_header Access-Control-Allow-Origin *;
}
2. В<script>
установить вcrossorigin="anonymous"
В вашем HTML-коде для вас установленоAccess-Control-Allow-Origin
каждого сценария, вscript
установить на этикеткеcrossorigin =“anonymous”
. добавить в тег scriptcrossorigin
Перед свойствами обязательно проверьте вышеуказанноеheader
отправил правильно.
В Firefox, если присутствует атрибут crossorigin, но отсутствует заголовок Access-Control-Allow-Origin, скрипт не будет выполняться.
5. TypeError: объект не поддерживает свойство
Это ошибка, возникающая в IE при вызове неопределенного метода. Вы можете протестировать его в консоли разработчика IE.
Это эквивалентно Chrome“TypeError:”undefined“ is not a function”
ошибка.
Да, разные браузеры могут иметь разные сообщения об одной и той же логической ошибке.
Это распространенная проблема с Internet Explorer для веб-приложений, использующих пространства имен JavaScript. В этом случае в 99,9% случаев причиной является то, что IE не может связать метод в текущем пространстве имен с ключевым словом this.
Например: если у вас есть пространство имен в JSRollbar
и методisAwesome
. Обычно, если выRollbar
namespace, вы можете использовать следующий синтаксис для вызоваisAwesome
метод:
this.isAwesome();
Chrome, Firefox и Opera с радостью примут этот синтаксис. Но IE нет. Таким образом, самый безопасный вариант при использовании пространств имен JS — всегда использовать префикс фактического пространства имен.
Rollbar.isAwesome();
6. TypeError: 'undefined' не является функцией
Это ошибка, возникающая в Chrome при вызове неопределенной функции. Вы можете протестировать в консоли разработчика Chrome и консоли разработчика Mozilla Firefox.
function clearBoard(){
alert("Cleared");
}
document.addEventListener("click", function(){
this.clearBoard(); // what is “this” ?
});
Выполнение приведенного выше кода приводит к следующей ошибке:
«Uncaught TypeError: this.clearBoard не является функцией».
Причина должна быть ясна, то есть ошибка указания, вызванная контекстом выполнения, непонятна.
7. Неперехваченная ошибка диапазона
Эта ошибка возникает при вызове рекурсивной функции, которая не завершается. Вы можете протестировать его в консоли разработчика Chrome.
Кроме того, это может произойти, если вы передаете значение функции, которая находится вне области действия.
Многие функции принимают в качестве входных значений только определенный диапазон чисел. Например:
-
toExponential(digits)
а такжеtoFixed(digits)
принимает от 0 до 100 -
toPrecision(digits)
Принимает от 1 до 100
var num = 2.555555;
console.log(num.toExponential(4)); //OK
console.log(num.toExponential(-2)); //range error!
console.log(num.toFixed(2)); //OK
console.log(num.toFixed(105)); //range error!
console.log(num.toPrecision(1)); //OK
console.log(num.toPrecision(0)); //range error!
8. Ошибка типа: невозможно прочитать свойство «длина»
Это ошибка, возникающая в Chrome из-за чтения свойства длины неопределенной переменной. Вы можете протестировать его в консоли разработчика Chrome.
Обычно вы найдете определенную длину в массиве, но вы можете столкнуться с этой ошибкой, если массив не инициализирован или если переменная находится в другом контексте. Давайте разберем эту ошибку на следующем примере.
var testArray = ["Test"];
function testFunction(testArray) {
for (var i = 0; i < testArray.length; i++) {
console.log(testArray[i]);
}
}
testFunction();
Выполнение приведенного выше кода вызовет ошибку:
Cannot read property 'length' of undefined
Есть два способа решить эту проблему:
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();
или
var testArray = ["Test"];
function testFunction(testArray) {
for (var i = 0; i < testArray.length; i++) {
console.log(testArray[i]);
}
}
testFunction(testArray);
9. Uncaught TypeError: Невозможно установить свойство
Когда мы пытаемся получить доступ к неопределенной переменной, она всегда возвращает неопределенное значение, и мы не можем получить или установить какие-либо неопределенные свойства. В этом случае будет выдано сообщение «Uncaught TypeError: Cannot set property».
10. ReferenceError: event is not defined
Эта ошибка возникает, когда вы пытаетесь получить доступ к неопределенной переменной или переменной, которая находится вне текущей области. Вы можете проверить в браузере Chrome.
Если вы столкнулись с этой ошибкой при использовании события, обязательно используйте объект события, переданный в качестве параметра. Старые браузеры, такие как IE, предоставляют событие глобальной переменной, но не все браузеры его поддерживают.
document.addEventListener("mousemove", function (event) {
console.log(event);
})
Суммировать
Мы видели 10 наиболее распространенных ошибок выше, но связанные с ними знания несложны. После того, как вы прочтете том 1 «JavaScript, которого вы не знаете», эти ошибки практически исчезнут.
Суть в отсутствии четкого понимания основ JavaScript.
План вывода статей, связанных с Vue
В последнее время друзья всегда спрашивали меня о Vue, поэтому я опубликую 10 статей, связанных с Vue, в надежде быть полезным для вас. Я буду обновлять один через 7-10 дней.
- Процесс внедрения Vuex в жизненный цикл Vue (завершено)
- Необходимый запас знаний для изучения исходного кода Vue (полный)
- Анализ принципа отзывчивости Vue (полный)
- Процесс исправления новых и старых VNodes
- Как разрабатывать функциональные компоненты и загружать в npm
- Оптимизируйте свой проект Vue с учетом этих аспектов
- Разработка внешнего интерфейса от Vue-Router design
- Как правильно использовать Webpack в проекте
- Сервер рендеринга Vue
- Как выбрать между Axios и Fetch
Предлагаю вам обратить внимание на мой официальный аккаунт и получать свежие статьи как можно скорее.