Слово «яма» означает «ловушка». Из -за характера «слабый язык» JavaScript он чрезвычайно свободен и гибкий во время использования, но его также очень легко «ударить». Эти ямы часто скрыты, поэтому вы должны держать глаза открытыми для плавания по дороге обучения и применения JS.
1. Глобальные переменные
JavaScript управляет областями по функциям. Переменные, объявленные внутри функции, находятся внутри этой функции и недоступны вне функции. С другой стороны, глобальные переменные объявляются вне какой -либо функции или используются просто и просто без объявления.
«Используйте его просто без объявления» означает, что переменные объявляются без использования ключевого слова VAR. Мы уже дали понять, что способ избежать неявного генерации глобальных переменных состоит в том, чтобы как можно больше объявлять переменные с ключевым словом VAR.
Но как вы думаете, можно использовать VAR? Давайте посмотрим на эту яму:
Кода -копия выглядит следующим образом:
функция foo () {
var a = b = 0;
// тело...
}
Может быть, то, что вы ожидаете, является двумя локальными переменными, но B является реальной глобальной переменной. Почему? Поскольку операция назначения справа от слева, так что это эквивалентно:
Кода -копия выглядит следующим образом:
функция foo () {
var a = (b = 0);
// тело...
}
Таким образом, B является глобальной переменной.
Заполните яму: объявления переменных, лучше всего прийти один за другим, не делайте оптом ~ _ ~;
2. ДЕКОЛОВАНИЕ ПАРИЧЕСКОЕ
Давайте сначала посмотрим на яму:
Кода -копия выглядит следующим образом:
myname = "global";
функция foo () {
оповещение (myname);
var myname = "local";
оповещение (myname);
}
foo ();
На первый взгляд, мы ожидаем, что результаты двух оповещений будут «глобальными» и «локальными» соответственно, но реальные результаты «неопределенные» и «локальные». Почему? Потому что переменные объявляются в одной и той же сфере (та же функция) и сначала проанализированы по вершине области.
Таким образом, поведение выполнения приведенного выше фрагмента кода может выглядеть так:
Кода -копия выглядит следующим образом:
функция foo () {
var myname;
оповещение (myname); // "неопределенный"
myname = "local";
оповещение (myname); // "местный"
}
Используйте другую яму, чтобы проверить, действительно ли вы понимаете предварительное начало:
Кода -копия выглядит следующим образом:
if (! ("a" в окне)) {
var a = 1;
}
предупреждение (а);
Объявление переменной продвигается к вершине кода и еще не было назначено. Затем введите заявление IF и судите, что установлено в окне «A» (A было объявлено как глобальная переменная), поэтому результат расчета выбора суждения является ложным, и оператор IF выпрыгнет, поэтому значение A не определено.
Кода -копия выглядит следующим образом:
var a; // "неопределенный"
console.log ("a" в окне); // истинный
if (! ("a" в окне)) {
var a = 1; // не выполнен
}
предупреждение (а); // "неопределенный"
Заполните яму: лучше всего разместить переменную объявление в верхнюю часть сферы действия. Для переменных, которые не могут быть назначены в данный момент, вы можете сначала использовать метод объявления, а затем назначить значения.
3. Объявление функции
Объявления функций также продвигаются к вершине масштаба и проанализированы и оценены до того, как какие -либо выражения и заявления будут проанализированы и оценены.
Кода -копия выглядит следующим образом:
оповещение (TypeOf foo); // "функция"
функция foo () {
// тело...
}
Вы можете сравнить это:
Кода -копия выглядит следующим образом:
оповещение (TypeOf foo); // "неопределенный"
var foo = function () {
// тело...
};
Если вы понимаете этот принцип, вы все равно попадете в следующие ловушки?
Кода -копия выглядит следующим образом:
функциональный тест () {
оповещение ("1");
}
тест();
функциональный тест () {
оповещение ("2");
}
тест();
При запуске приведенного выше фрагмента кода всплывающие окна, которые вы видите, являются «2», почему они не «1» и «2» соответственно? Это очень просто, объявление теста анализируется до тестирования (). Поскольку последний переопределяет первое, результат обеих казней - «2».
Заполните яму: в большинстве случаев я использую экспрессии функций вместо объявлений функций, особенно в некоторых блоках операторов.
4. Функциональные выражения
Давайте сначала посмотрим на выражение именованной функции. Конечно, у него должно быть имя, например:
Скопируйте код следующим образом: var bar = function foo () {
// тело...
};
Следует отметить, что имя функции видно только для ее функции внутри. Такие как следующие ошибки:
Кода -копия выглядит следующим образом:
var bar = function foo () {
foo (); // запустить нормально
};
foo (); // Ошибка: ссылка
Заполните яму: попробуйте использовать именованные выражения функции как можно меньше (за исключением некоторых целей рекурсии и отладки), и никогда не используйте имена функций внешне.
5. Функция самовосставления
Для выражений функции вы можете выполнить, добавив () после этого, а параметры могут передаваться в скобках, в то время как объявление функции не может. яма:
Кода -копия выглядит следующим образом:
// (1) Это просто оператор группировки, а не вызов функции!
// Таким образом, функция здесь не была выполнена, она все еще является оператором
функция foo (x) {
предупреждение (x);
} (1);
Следующие фрагменты кода выполняются отдельно, а всплывающее окно показывает «1». Потому что до (1) они являются экспрессией функций, поэтому () здесь не является оператором группировки, а оператором, указывающим на выполнение вызова.
Скопируйте код следующим образом: // Стандартное выражение анонимной функции
var bar = function foo (x) {
предупреждение (x);
} (1);
// предыдущий () преобразует объявление функции в выражение
(функция foo (x) {
предупреждение (x);
}) (1);
// все () является выражением
(функция foo (x) {
предупреждение (x);
} (1));
// новое выражение
новая функция foo (x) {
предупреждение (x);
} (1);
// &&, ||,!, +, -, ~ и т. д.
// Таким образом, как только сиятель узнает, что один из них является выражением, другие также будут по умолчанию в выражениях.
true && function foo (x) {
предупреждение (x);
} (1);
Заполните яму: ключ к этой яме - выяснить сущность всех видов выражений функций.
6. Закрытие в петле
Следующее демонстрирует общую ловушку:
Кода -копия выглядит следующим образом:
<! Doctype html>
<html lang = "en">
<голова>
<meta charset = "utf-8">
<title> документ </title>
</head>
<тело>
<h3> При нажатии на ссылки ниже, покажите номер ее последовательности </h3>
<ul>
<li> <a href = " #"> ссылка #0 </a> </li>
<li> <a href = " #"> ссылка #1 </a> </li>
<li> <a href = " #"> ссылка #2 </a> </li>
<li> <a href = " #"> ссылка #3 </a> </li>
<li> <a href = " #"> ссылка #4 </a> </li>
</ul>
</body>
</html>
Кода -копия выглядит следующим образом:
var links = document.getElementsbytagname ("ul") [0] .getelementsbytagname ("a");
для (var i = 0, l = links.length; i <l; i ++) {
ссылки [i] .onclick = function (e) {
e.preventdefault ();
Alert («Вы нажимаете ссылку #» + i);
}
}
Мы ожидаем, что при нажатии на ссылку I-TH мы получаем значение индекса I в этой последовательности. Однако независимо от того, какая ссылка нажимается, мы получаем конечный результат I после цикла: «5».
Объясните причину: когда вызывается оповещение, выражение анонимной функции в цикле для цикла поддерживает ссылку на внешнюю переменную I (закрытие). В настоящее время цикл закончился, и значение I изменяется на «5».
Заполните яму: чтобы получить желаемый результат, вам нужно создать копию переменной I в каждом цикле. Следующее демонстрирует правильный подход:
Кода -копия выглядит следующим образом:
<голова>
<meta charset = "utf-8">
<title> документ </title>
</head>
<тело>
<h3> При нажатии на ссылки ниже, покажите номер ее последовательности </h3>
<ul>
<li> <a href = " #"> ссылка #0 </a> </li>
<li> <a href = " #"> ссылка #1 </a> </li>
<li> <a href = " #"> ссылка #2 </a> </li>
<li> <a href = " #"> ссылка #3 </a> </li>
<li> <a href = " #"> ссылка #4 </a> </li>
</ul>
</body>
</html>
Кода -копия выглядит следующим образом:
var links = document.getElementsbytagname ("ul") [0] .getelementsbytagname ("a");
для (var i = 0, l = links.length; i <l; i ++) {
ссылки [i] .onclick = (function (index) {
возврат функции (e) {
e.preventdefault ();
Alert ("Вы нажимаете ссылку #" + index);
}
})(я);
}
Как вы можете видеть, форма (function () {...}) ()-это самообслуживание функции, упомянутой выше. Я передан в индекс в качестве параметра. Когда Alert снова выполняется, у него есть ссылка на индекс. В настоящее время это значение не будет изменено петлей. Конечно, после понимания принципа, вы также можете написать так:
Кода -копия выглядит следующим образом:
для (var i = 0, l = links.length; i <l; i ++) {
(function (index) {
ссылки [i] .onclick = function (e) {
e.preventdefault ();
Alert ("Вы нажимаете ссылку #" + index);
}
})(я);
}
Это тоже работает.