Вложенная функция JavaScript

97

У меня есть фрагмент кода для javascript, который я просто не понимаю:

function dmy(d) {
    function pad2(n) {
        return (n < 10) ? '0' + n : n;
    }

    return pad2(d.getUTCDate()) + '/' +
       pad2(d.getUTCMonth() + 1) + '/' +
       d.getUTCFullYear();
}

function outerFunc(base) {
    var punc = "!";

    //inner function
    function returnString(ext) {
       return base + ext + punc;
    }

    return returnString;
}

Как можно определить функцию в другой функции? Можем ли мы вызвать pad2 () извне моей функции ()?

Пожалуйста, осветите это. Спасибо

Томас
источник
13
функции могут быть созданы внутри функций. Это совершенно верно.
0x499602D2 03

Ответы:

140

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

Функции, определенные в другой функции, не будут доступны вне функции, если они не были прикреплены к объекту, доступному за пределами функции:

function foo(doBar)
{
  function bar()
  {
    console.log( 'bar' );
  }

  function baz()
  {
    console.log( 'baz' );
  }

  window.baz = baz;
  if ( doBar ) bar();
}

В этом примере функция baz будет доступна для использования после того, как fooфункция будет запущена, поскольку она переопределена window.baz. Функция панели не будет доступна для любого контекста, кроме областей, содержащихся в fooфункции.

в качестве другого примера:

function Fizz(qux)
{
  this.buzz = function(){
    console.log( qux );
  };
}

FizzФункция предназначена как конструктор , так что при запуске он назначает buzzфункцию для вновь созданного объекта.

zzzzBov
источник
Что такое window.baz = baz? Почему эта линия m? Ke baz доступна?
Ziyang Zhang
@ZiyangZhang, абзац после этого блока кода содержит объяснение, была ли какая-то часть неясной?
zzzzBov
35

Это называется закрытием .

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

Это очень мощная функция. Вы можете увидеть больше объяснений здесь:

javascript_closures_for_dummies.html зеркало на Archive.org

Тадек
источник
13
function x() {}

эквивалентно (или очень похоже) на

var x = function() {}

если я не ошибаюсь.

Так что ничего смешного не происходит.

Андреас
источник
8
Первый синтаксис будет перемещен в начало документа. так что можно вызвать функцию «x» до инициализации функции.
Tom
10
Первый синтаксис также даст вам гораздо более удобную трассировку стека с именованными функциями, второй вызовет у вас головную боль
TheZ
@TheZ Я думаю, что Chrome недавно добавил вывод имени функции для отладки, поэтому у вас не будет такой же головной боли, как раньше в общем случае.
jinglesthula
@jinglesthula Да!
Некоторое
10

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

function foo() {
    function bar() {
        return 1;
    }
    return bar();
}

fooманипулирует barвнутри себя. barнельзя касаться из внешней области, если она не определена во внешней области.

Так что это не сработает:

function foo() {
    function bar() {
        return 1;
    }
}

bar(); // throws error: bar is not defined
0x499602D2
источник
4

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

Все переменные, существующие в dmy, видны в pad2, но не бывает наоборот: D

педрочавес
источник
2

В Javascript (и во многих языках) совершенно нормально иметь функции внутри функций.

Найдите время, чтобы выучить язык, не используйте его на том основании, что он похож на то, что вы уже знаете. Я бы посоветовал посмотреть серию презентаций YUI на Javascript Дугласа Крокфорда с особым акцентом на Act III: Function the Ultimate (ссылка на загрузку видео, слайды и стенограмму)

Хоаким Рендейро
источник
0

function foo() {
  function bar() {
    return 1;
  }
}
bar();

Выдает ошибку. Поскольку barопределено внутри foo, barбудет доступно только внутри foo.
Для использования barнужно запустить его внутрь foo.

function foo() {
  function bar() {
    return 1;
  }
  bar();
}

Джастин Лю
источник