2011-08-10 2 views
8

Я получаю странное поведение при объявлении объекта с логическим ИЛИ.Объявить переменную без ключевого слова var и логическое ИЛИ

my_var = my_var || {}; // throws TypeError 

Если я добавляю var ключевое слово

var my_var = my_var || {}; // returns empty object 

Почему это? Кажется, я не могу найти объяснения. my_var - глобальный масштаб, так почему же var меняет поведение?

+0

Не могли бы вы предоставить немного больше кода? Является ли my_var ранее установленным в сценарии в какой-то момент в пределах той же области? я бы предположил так. –

+0

Да, 'my_var' должен быть объявлен на ранней стадии исполнения. В частности, в другом источнике JavaScript. Я столкнулся с этим во время тестирования в IE8. FireFox вел себя так, как ожидалось, но в IE8 я столкнулся с некоторыми проблемами времени выполнения. Эта тайна возникла, когда я пытался отлаживать. –

+0

Все это звучит как повод для фактического явного проверки для неопределенного, для меня. – Kzqai

ответ

5

Первый пример пытается присвоить свойству на глобальный объект с именем my_var путем считывания значения из идентификатора называется my_var (OR пустой объект). Однако идентификатор my_var не определен в этой точке, поэтому он терпит неудачу.

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

также посмотреть на этом примере:

a = a; // fails, undeclared identifier 
a = 0; 

С вар ключевым словом, он будет работать!

b = b; // succeeds allthough identifier undeclared?! 
var b = 0; 

Это происходит потому, что переменная Подъемный превратит его в этом:

var b; // declaration of b hoisted to the top of scope 
b = b; 
b = 0; 
0

Во 2-й ситуации, моя переменная не определена, поэтому переменной присваивается пустой объект, который {}

1

В вашем втором примере var определяет сферу my_var. Это позволяет правильно установить значение. Вот быстрый и грязный взгляд на то, что происходит в обоих примерах:

С примера 1, двигатель JS должен сделать следующее:

  1. Проверьте текущий масштаб, чтобы увидеть, если my_var существует.
  2. Проверьте область действия (и область действия выше этого), пока она не найдет my_var.
  3. Создание my_var в глобальном масштабе, когда он не нашел. *

* Шаг 3 еще не произошло при попытке присвоить значение my_var.

Пример 2:

  1. Есть ли переменная с именем my_var в текущей области? Да, вы только что создали его, используя ключевое слово var.
  2. Назначьте его значение.
0

Хотя я не могу процитировать спецификации, я предполагаю, что инициализация в var заявления просто синтаксический сахар:

var my_var = my_var || {}; 

эквивалентен:

var my_var; 
my_var = my_var || {}; 

В первой строке my_var объявлено и неявно установлено на специальное значение undefined. Затем во второй строке my_var существует, undefined оценивает до false и ошибка не возникает.

В вашем первом примере, однако, my_var неизвестен, когда оценивается правая сторона, следовательно, ошибка.

+0

Правильно, но почему 'var' меняет объявление? У 'var' есть уникальная функция для инициализации' my_var'. Или другой способ взглянуть на это, почему «var» изменяет поведение логического ИЛИ? –

+0

'var' не изменяет поведение OR! 'var' объявляет переменную * local * и присваивает ей значение' undefined'. Объявление переменной без 'var' создает переменную * global *. –

1

при определении переменной без var, вы напрямую обращаетесь к global object. Это означает, что ваш механизм Javascript пытается найти my_var на глобальном объекте (window, если вы в браузере). Поскольку это свойство еще не существует, ваш JS-движок будет бросать.

Что вы делаете на правой стороне вашего заявления, когда ваш движок пытается прочитать переменную с именем my_var. присвоение, как

my_var = {}; 

будет работать tho. Но доступ к идентификатору без var приведет к тому, что браузер проведет поиск в области охвата. Поскольку variable object для глобального объекта является самим глобальным объектом, процедура поиска будет в никуда (= исключение).

Поставив ключевое слово var infront, ваш js-движок знает в парагенеме, что он должен объявить новую переменную с этим именем идентификатора. Он фактически объявляет эту переменную величиной undefined (называемой «подъем»). Это означает, что использование var преждевременно создаст свойство в current context с этим именем. Поэтому, если этот код не находится в какой-либо функции или в контексте eval, он создаст свойство my_var на объекте window.

0

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

my_var = a || {}; 

во втором случае my_var только не определено, как вы используете УАК ключевое слово, могут создать my_var в действительном объеме. Undefined преобразуется в false и возвращает пустой объект.

0

Интересно, что это будет работы:

a = my_var || {}; // 'a' is now an empty object 

При использовании «Var» ключевое слово, вы в буквальном смысле дает команду «создать новую переменную и присвоить ей это значение.» Если вы не используете «var», вы подразумеваете, что переменная уже существует в пределах глобальной области где-то.

В вашем примере движок JavaScript пытается найти текущее значение «my_var», обнаружив, что его нет, не может его создать, потому что вы в настоящее время пытаетесь присвоить ему значение и не выполняете его.

Смежные вопросы