Вопрос

Сегодня я обсуждал с коллегой вложенные функции в Javascript:

function a() {
   function b() {
      alert('boo')
   }
   var c = 'Bound to local call object.'
   d = 'Bound to global object.'
}

В этом примере испытания показывают, что b недостижимо вне тела a, как и c.Однако d — после выполнения a().Ищем точное определение этого поведения в Стандарт ECMAScript v.3 , я не нашел именно той формулировки, которую искал;что не сказано в разделе 13, стр. 71, так это то, к какому объекту должен быть привязан объект функции, созданный оператором объявления функции.Я что-то пропустил?

Это было полезно?

Решение

Это статическая область видимости.Операторы внутри функции ограничены этой функцией.

Однако Javascript имеет необычное поведение: без вар ключевое слово, вы подразумевали глобальная переменная.Это то, что вы видите в своем тесте.Ваша переменная «d» доступна, поскольку она является подразумеваемой глобальной, несмотря на то, что она записана в теле функции.

Также, чтобы ответить на вторую часть вашего вопроса:Функция существует в любой области видимости, как и переменная.

Примечание: Вероятно, вам не нужны глобальные переменные, особенно неявные.Рекомендуется всегда использовать ключевое слово var, чтобы избежать путаницы и сохранить чистоту.

Примечание:Стандарт ECMA, вероятно, не самое полезное место для поиска ответов о Javascript, хотя это определенно неплохой ресурс.Помните, что javascript в вашем браузере — это всего лишь реализация этого стандарта, поэтому документ по стандартам будет содержать правила, которым (в основном) следовали разработчики при создании движка javascript.Он не может предоставить конкретную информацию о интересующих вас реализациях, а именно об основных браузерах.В частности, есть пара книг, которые дадут вам очень прямую информацию о том, как ведут себя реализации javascript в основных браузерах.Чтобы проиллюстрировать разницу, я приведу ниже выдержки из спецификации ECMAScript и книги по Javascript.Я думаю, вы согласитесь, что книга дает более прямой ответ.

Вот из Спецификация языка ECMAScript:

10.2 Вход в контекст выполнения

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

Когда элемент управления входит в контекст выполнения, цепочка областей создается и инициализируется, выполняется переменная экземпляра, и это значение определяется.

Инициализация цепочки объема, переменной экземпляры и определение этого значения зависят от типа введенного кода.

Вот из О'Рейли Javascript:Полное руководство (5-е издание):

8.8.1 Лексическая область видимости

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

Для освещения подобных вопросов настоятельно рекомендуется прочитать книгу Дугласа Крокфорда:

JavaScript, хорошие детали http://oreilly.com/catalog/covers/9780596517748_cat.gif

Javascript, Хорошие стороны, также от О'Рейли.

Другие советы

Насколько я понимаю, они эквивалентны с точки зрения области видимости:

function a() { ... }

и

var a = function() { ... }

Кажется важным отметить, что хотя d создается как «глобальный», в действительности он создается как свойство объекта window. Это означает, что вы можете случайно перезаписать то, что уже существует в объекте окна, или ваша переменная может вообще не быть создана. Итак:

function a() {
    d = 'Hello World';
}
alert(window.d); // shows 'Hello World'

Но вы не можете сделать:

function a() {
    document = 'something';
}

потому что вы не можете перезаписать объект window.document.

Для практических целей вы можете представить, что весь ваш код выполняется в гигантском блоке с (окном) .

Javascript имеет две области действия. Глобальный и функциональный. Если вы объявляете переменную внутри функции, используя " var " ключевое слово, оно будет локальным для этой функции и любых внутренних функций. Если вы объявляете переменную вне функции, она имеет глобальную область видимости.

Наконец, , если вы опускаете ключевое слово var при первом объявлении переменной, javascript предполагает, что вам нужна глобальная переменная, независимо от того, где вы ее объявляете .

Итак, вы вызываете функцию a, а функция a объявляет глобальную переменную d.

...

function a() {
   function b() {
      alert('boo')
   }
   var c = 'Bound to local call object.'
   d = 'Bound to global object.'
}

без предшествования вар, d является глобальным.Сделайте это, чтобы сделать d приватным:

function a() {
   function b() {
      alert('boo')
   }
   var c = 'Bound to local call object.'
   var d = 'Bound to local object.'
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top