Почему имя функции исчезает при назначении переменной var?
Я пытаюсь получить более глубокое понимание того, как работает Javascript, и следующий код прослушивает меня:
function notInVar(a, b) {
return a + b
}
var inVar = function doesThisWork(a, b) {
return a + b
}
document.writeln('2 + 2 = ' + notInVar(2, 2));
document.writeln('3 + 3 = ' + inVar(3, 3));
document.writeln('4 + 4 = ' + doesThisWork(4, 4));
В Chrome первые два файла document.writelns выполняются так, как ожидалось, затем я получаю "Uncaught ReferenceError: doesThisWork is not defined"
в Chrome. Почему я не могу вызвать вторую функцию по имени doesThisWork
? В этом случае, где хранится первый объект-объект notInVar?
Ответы
Ответ 1
Функции - это объекты. Переменная inVar
содержит объект функции с именем doesThisWork
.
inVar.name //=> "doesThisWork"
Если функция не имеет имени, она анонимна.
Чтобы вызвать функцию, хранящуюся в переменной, вы используете имя переменной (ссылка на этот объект). Если вы хотите вызвать функцию внутри той же функции (для рекурсии), вы можете вызвать ее по ее имени, в этом случае doesThisWork
.
Ответ 2
Второе определение называется названное выражение функции и из-за характера этого определения, единственный способ, которым вы можете назвать его по имени, - это изнутри тела функции:
var inVar = function doesThisWork(a, b) {
return doesThisWork(a + b); // infinite recursion!
}
Это может быть использовано для достижения рекурсии внутри анонимной функции, без необходимости использовать что-то вроде Y-combinator.
Ответ 3
В этом случае, где хранится первый объект-объект notInVar?
function notInVar(a, b) {
return a + b
}
Является эквивалентным
var notInVar = function (a, b) {
return a + b
}
В вашем случае notInVar
хранится в глобальной области.
тогда я получаю сообщение "Uncaught ReferenceError: doesThisWork не определено" в Chrome
var inVar = function doesThisWork(a, b) {
return a + b
}
похож на
var inVar = function (a, b) {
return a + b
}
когда он обратился к вне функции
Вы не можете получить доступ к функции с помощью doesThisWork
, но вам нужно получить к ней доступ inVar
Ответ 4
Как вы его написали, doesThisWork
доступен только внутри себя.
Ответ 5
Функция - это переменная, и область действия переменной имеет значение. Для второй функции в глобальной области ее имя переменной InVar. Имя функции doesThisWork находится внутри собственной области видимости и не отображается в глобальной области. Поэтому вы можете использовать inVar, а не doesThisWork.
Ответ 6
Ну, есть несколько вещей об этом:
сначала: имя функции будет локальным, поэтому вы можете вызывать одну и ту же функцию только внутри локально. который может вызвать бесконечную рекурсию при ее использовании, если она не будет отфильтрована как if(doesThisWork.caller != doesThisWork) return doesThisWork(a,b);
.
Вторым является то, что вы назначаете имя функции (не оставляя ее как анонимную функцию), а локально к ней.
TL; DR = > перейти к анализу для более четкой идеи.
Интересно отметить различия между методами объявления функций:
встроенное объявление:
var x = function fnName(){}; console.log(x.prototype); => fnName {} // but used locally to x
var x = function(){}; console.log(x.prototype); => Object {} // no local name, only global x
во время разбора/времени выполнения:
function fnName(){}; console.log(fnName.prototype); => fnName {} // global* and local name
Мой анализ: заключается в том, что локальность здесь обусловлена назначением, так как когда вы объявляете функцию внутри функции, это имя будет использоваться локально для содержащей функции, а не вне нее, то же самое для переменной, которая содержит функцию, так как она содержит ее и ее имя. все же переменная, содержащая эту функцию, может быть использована в ней, поскольку она является локальной для нее контейнерной функцией, которая является другой областью.
* глобальный здесь означает глобальное расположение функции не в документе. поскольку он является локальным для него контейнером, но глобальным для других объектов в одном контейнере.