Яка різниця між глобальним var і window.variable в javascript?


76

Я читаю документи backbone.js і бачу багато коду, який призначає атрибути об'єкту window:

window.something = "whatever";

в чому різниця між викликом цього коду і просто присвоєнням змінної та створенням глобальної змінної, як це:

something = "whatever";

Я припускаю, що існує якась інша сфера дії, та / або різниця у власності на об'єкт (вікно є власником проти, а не), але мене цікавлять деталі між ними та чому я б використовував window vs, щоб не використовувати його.


2
Це на самому ділі не пов'язано з вашого конкретного випадку, але пам'ятайте , що Javascript НЕ повинні працювати в браузері, так що вікно не має бути визначений.
Андрій Барсан,

Відповіді:


75

Без різниці. Вони обидва мають однаковий ефект (у браузері, де windowє глобальний контекст 1 ).

  • window.foo = "bar"встановлює властивість fooна window.
  • foo = "bar"позначає або друкарську помилку, або навмисно глобальну.

Оскільки мені доводиться ще раз перевіряти, чи це друкарська помилка, чи ні, я особисто вважаю, що це читабельніше встановлювати window.fooбезпосередньо.

Крім того, у суворому режимі ES5 foo = "bar"є незаконним призначенням, оскільки fooне задекларовано і викине a Error.

Редагувати:

Як зазначалося в коментарях, foo = "bar"буде шукати весь ланцюжок обсягу для змінної fooта повторно призначити її, "bar"якщо вона знайдена. Якщо його не знайти, він створить нову глобальну змінну.

Крім того, window.foo = "bar"ви просто присвоюєте властивість об'єкту, який можна видалити за допомогою delete window.foo.

У строгому режимі ES5 для змінної неприпустимоdelete .


1 В інших середовищах, таких як node.js та Web Workers, може існувати інша назва глобального об'єкта і windowможе взагалі не існувати. Використання Node.js globalта веб-працівників self.


4
Окрім того, ви можете видалити window.foo, але не глобальний foo, визначений за допомогою var.
kennebec

8
Різниця є. window.foo = bar;встановлює foo на об'єкт вікна. foo = bar;шукає ланцюжок обсягу, поки не знайде foo, що в кінцевому підсумку може стати глобальним об’єктом, але не завжди.
Девід

@kennebec Я вважаю, що це специфічно для браузера.
Raynos

@Raynos: Різниця в можливості видалення насправді не залежить від браузера. Відповідно до специфікації ECMAScript і припускаючи, що windowце глобальний об'єкт, поведінка, яку описує @kennebec, є правильною. Однак старіші версії IE не відповідають.
Тім Даун

@TimDown Це не повинно бути специфічним для браузера, але воно є. Однак я погоджуюсь, що специфікація ES говорить, що ви можете видаляти властивості.
Raynos

10

Вони обидва роблять одне і те ж.
Але, отримуючи доступ до windowвластивості, ви точно знаєте, що отримуєте доступ до глобальної змінної незалежно від того, в якій області ви знаходитесь.
Наприклад:

globalVar = "smth";
function(){
    var globalVar = 2;
    alert(globalVar);// points to the current scope globalVar
    alert(window.globalVar);// points to the original globalVar
}

Іншими словами, якщо ви хочете працювати з глобалами, доступ до них через їх контейнер є дещо безпечнішим: window.variable


5

Ключ, як натякав Рейнос, полягає в тому, що він явно встановлений на об'єкті вікна. У браузері глобальний об'єкт є тим самим, що і віконний об'єкт, але в інших середовищах (наприклад, node.js або, можливо, якийсь веб-перегляд на мобільному пристрої) може цього не робити.


2

Різниця полягає в тому, що window.foo = bar;їх неможливо перехопити шляхом рефакторингу, зробленого пізніше. Використання foo = bar;означає, що якщо пізніше код буде переміщено в закриття, де var fooбуло визначено, він більше не встановлюватиме його на глобальному об'єкті.


0

Додавання ще одного пункту:

Якщо ви безпосередньо посилаєтесь на незадекларовану змінну (без використання - window або typeof ), ви отримаєте помилку, не визначену змінною .

Приклади:

// var unDecVariable

if (unDecVariable != null) // Error: unDecVariable is not defined
{
    // do something
}

if (window.unDecVariable != null) // No Error
{
    // do something
}

if (typeof unDecVariable != 'undefined' && unDecVariable != null) // Alternative way
{
    // do something
}

0

Невирішені посилання (вони ж незадекларовані змінні) насправді не є змінними, вони додаються як властивість до глобального об'єкта. [5c]

У строгому режимі ("використовувати строго") невирішені посилання викидають ReferenceError. Це робиться для того, щоб уникнути додавання властивостей до глобального об’єкта, які мали бути оголошені змінними. У цьому випадку, якщо ви хочете додати властивість до глобального об'єкта, ви б використовували window.foo = "bar". [5a]

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.