Область JavaScript в блоке try
Скажем, я пытаюсь выполнить этот фрагмент кода JavaScript. Предположим, что необъявленные vars и методы объявлены в другом месте выше и что something
и somethingElse
оцениваются как boolean-true.
try {
if(something) {
var magicVar = -1;
}
if(somethingElse) {
magicFunction(magicVar);
}
} catch(e) {
doSomethingWithError(e);
}
Мой вопрос: каков объем magicVar
и можно ли передать его в magicFunction
, как я это сделал?
Ответы
Ответ 1
Javascript имеет область действия. Это означает, что magicvar
будет существовать с самого начала функции, которая была объявлена до конца этой функции, даже если это утверждение никогда не выполняется. Это называется переменной подъема. То же самое происходит с объявлениями функций, которые, в свою очередь, называются функцией hoisting.
Если переменная объявлена в глобальной области видимости, она будет видна всем. Это часть причины, по которой глобальные переменные считаются злыми в Javascript.
Ваш пример передаст undefined
в magicFunction
, если something
является false, потому что magicvar
не назначено никому.
Хотя это технически обоснованный Javascript, он обычно считается плохим стилем и не будет проходить шашки стиля, такие как jsLint. Чрезвычайно неинтуитивный Javascript, подобный этому, будет выполняться без ошибок
alert(a); //alerts "undefined"
var a;
POP QUIZ: что делает следующий код?
(function() {
x = 2;
var x;
alert(x);
})();
alert(x);
Ответ 2
Много других хороших ответов о том, как Javascript обрабатывает это с помощью var
, но я думал, что рассмотрю ситуацию let
...
Если переменная определена с помощью let
внутри блока try
, она НЕ будет в области видимости внутри блоков catch
(или finally
). Он должен быть определен в закрывающем блоке.
Например, в следующем блоке кода выход консоли будет "Outside":
let xyz = "Outside";
try {
let xyz = "Inside";
throw new Error("Blah");
} catch (err) {
console.log(xyz);
}
Ответ 3
- Только в функциях javascript создается новый контекст-закрытие.
- Каждое определение переменной действительно является объявлением переменной в верхней части ее области и назначением в том месте, где определено определение.
вар
- функция в области видимости
- подъемник вверху своей функции
- переопределение одного и того же имени в той же области действия no-ops
Возможно, вы захотите прочитать листы обманывания MDN
Из-за hoisting
Вы можете даже делать такие вещи:
function bar() {
var x = "outer";
function foo() {
alert(x); // {undefined} Doesn't refer to the outerscope x
// Due the the var hoising next:
x = 'inner';
var x;
alert(x); // inner
}
foo();
}
bar();
bar();
Демо
Итак, функция foo
преобразуется в нечто вроде этого:
function foo() {
var x;
alert(x); // {undefined} Doesn't refer to the outerscope x
// Due the the var hoising next:
x = 'inner';
alert(x); // inner
}
Мой вопрос: каков объем magicVar, и хорошо ли передать его в magicFunction, как я это сделал?
Определите все в порядке... Да, код действительно, но он менее читабельен, если объявления переменных были сверху, что все.
Ответ 4
Из-за javascript "hoisting" (google it) код объявления переменной преобразуется как:
function yourFunction() {
var magicVar;
try {
if(something) {
magicVar = -1;
}
if(somethingElse) {
magicFunction(magicVar);
}
} catch(e) {
doSomethingWithError(e);
}
} //end of your function
"Подъем" перемещает все объявления переменных в начало функции. Поэтому magicVar
доступен везде в функции, но undefined, пока вы не придадите ему значение.
У вашей переменной есть область действия.
Ответ 5
С var
переменные существуют от начала функции до конца, независимо от того, где они объявлены, или даже если утверждение действительно достигнуто. Тем не менее, они будут undefined
, пока не будут присвоены другое значение.
Итак, в вашем случае, если something
является ложным, но somethingelse
является истинным, вы вызываете magicFunction
с его первым аргументом undefined
.
Ключевое слово let
, созданное в Javascript 1.9 и доступное (на сегодняшний день, май 3 rd 2012, и, насколько я знаю) только в Firefox, объявляет переменные с семантикой области, которую вы Вероятно, он использовал.