Чи є різниця між оголошенням змінної:
var a=0; //1
...сюди:
a=0; //2
... або:
window.a=0; //3
в глобальному масштабі?
Чи є різниця між оголошенням змінної:
var a=0; //1
...сюди:
a=0; //2
... або:
window.a=0; //3
в глобальному масштабі?
Відповіді:
Так, є кілька відмінностей, хоча в практичному плані вони зазвичай не великі.
Є четвертий шлях, а станом на ES2015 (ES6) є ще два. Я додав четвертий шлях наприкінці, але вставив ES2015 способи після №1 (ви зрозумієте, чому), тож у нас є:
var a = 0; // 1
let a = 0; // 1.1 (new with ES2015)
const a = 0; // 1.2 (new with ES2015)
a = 0; // 2
window.a = 0; // 3
this.a = 0; // 4
№1 var a = 0;
Це створює глобальну змінну, яка також є властивістю глобального об'єкта , до якого ми отримуємо доступ як windowу браузерах (або через thisглобальну область застосування, у не строгому коді). На відміну від деяких інших властивостей, властивість неможливо видалити за допомогою delete.
У термінах специфікації, він створює ідентифікатор, що прив'язує до об'єкта Запис середовища для глобального середовища . Це робить його властивістю глобального об'єкта, оскільки глобальний об'єкт - це місце, де зберігаються прив'язки ідентифікаторів для об'єкта глобального середовища. Ось чому властивість не можна видалити: це не просто проста властивість, це прив'язка до ідентифікатора.
Прив'язка (змінна) визначається до запуску першого рядка коду (див. "Коли varце відбувається" нижче).
Зауважте, що в IE8 та новіших версіях властивість, створена на window, не перелічується (не відображається у for..inвиписках). В IE9, Chrome, Firefox та Opera це безліч.
№ 1.1 let a = 0;
Це створює глобальну змінну, яка не є властивістю глобального об'єкта. Це нова річ, що стосується ES2015.
В умовах специфікації, він створює ідентифікатор, прив'язуючи до декларативного запису середовища для глобального середовища, а не для об'єкта Environment Record. Глобальне середовище унікальна в тому , розкол по навколишньому середовищу записи, один для всіх старих речей , яка йде на глобальний об'єкт ( об'єкт Environment Record) і інший для всіх нових речей ( let, constі функції , створені class) , які не роблять перейти на глобальний об’єкт.
Прив'язка створюється до того, як буде виконано будь-який покроковий код у своєму блоку, що вкладається, (у цьому випадку до запуску будь-якого глобального коду), але воно жодним чином недоступне, поки покрокове виконання не досягне letзаяви. Як тільки виконання досягає letоператора, змінна стає доступною. (Див. "Коли letі коли constстанеться" нижче.)
№ 1.2 const a = 0;
Створюється глобальна константа, яка не є властивістю глобального об'єкта.
constточно так, letза винятком того, що ви повинні надати ініціалізатор ( = valueчастину), і ви не можете змінити значення константи після її створення. Під обкладинками це точно так, letале якщо прапор на прив'язці ідентифікатора говорить, що його значення не можна змінити. Використання constробить для вас три речі:
№2 a = 0;
Це створює властивість глобального об'єкта неявно . Оскільки це звичайна властивість, ви можете її видалити. Я рекомендую цього не робити, тому хтось може читати ваш код пізніше. Якщо ви використовуєте суворий режим ES5, це робить (призначаючи неіснуючу змінну) - помилка. Це одна з кількох причин використовувати суворий режим.
І що цікаво, знову ж таки в IE8 і раніше створене властивість не перелічується (не відображається у for..inвиписках). Це дивно, особливо це стосується №3 нижче.
№3 window.a = 0;
Це створює властивість глобального об'єкта явно, використовуючи windowглобальний, який посилається на глобальний об'єкт (у браузерах; деякі середовища, які не є браузером, мають еквівалентну глобальну змінну, наприклад, globalу NodeJS). Оскільки це звичайна властивість, ви можете її видалити.
Це властивість є перелічуваних, на IE8 і більш ранні версії, а також на будь-якому іншому браузері я пробував.
№4 this.a = 0;
Так само, як №3, за винятком того, що ми посилаємось на глобальний об’єкт, thisа не на глобальний window. Це не буде працювати в суворому режимі, оскільки в суворому режимі глобальний код thisне має посилання на глобальний об'єкт ( undefinedнатомість він має значення ).
Що я маю на увазі під "видаленням" чи "видаленням" a? Саме це: Видалення властивості (повністю) за допомогою deleteключового слова:
window.a = 0;
display("'a' in window? " + ('a' in window)); // displays "true"
delete window.a;
display("'a' in window? " + ('a' in window)); // displays "false"
deleteповністю видаляє властивість з об’єкта. Ви не можете цього зробити із властивостями, доданими windowопосередковано через var, deleteабо мовчки ігнорується, або викидає винятки (залежно від реалізації JavaScript та того, чи перебуваєте ви в суворому режимі).
Попередження : IE8 знову (і, мабуть, раніше, і IE9-IE11 у порушеному режимі "сумісності"): Це не дозволить вам видалити властивості windowоб'єкта, навіть коли вам це дозволять. Що ще гірше, він викидає виняток при спробі ( спробуйте цей експеримент в IE8 та інших браузерах). Тому при видаленні з windowоб'єкта ви повинні бути захисними:
try {
delete window.prop;
}
catch (e) {
window.prop = undefined;
}
Це намагається видалити властивість, і якщо буде викинуто виняток, він робить наступне найкраще і встановлює властивість undefined.
Це стосується лишеwindow об'єкта, і лише (наскільки я знаю) до IE8 і раніше (або IE9-IE11 у порушеному режимі "сумісності"). Інші веб-переглядачі відмінно видаляють windowвластивості, дотримуючись вищезазначених правил.
varце станетьсяЗмінні , визначені з допомогою varзаяви створюються до будь-якої крок за кроком код в контексті виконання виконується, і тому властивість існує добре перед тим в varзаяві.
Це може бентежити, тому давайте подивимось:
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "undefined"
display("bar in window? " + ('bar' in window)); // displays "false"
display("window.bar = " + window.bar); // displays "undefined"
var foo = "f";
bar = "b";
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "f"
display("bar in window? " + ('bar' in window)); // displays "true"
display("window.bar = " + window.bar); // displays "b"
Живий приклад:
Як бачите, символ fooвизначається перед першим рядком, але символ bar- ні. Там, де є var foo = "f";твердження, є насправді дві речі: визначення символу, яке відбувається до запуску першого рядка коду; і виконувати призначення цього символу, що відбувається там, де лінія знаходиться в покроковому потоці. Це відомо як " varпідйом", тому що var fooчастина переміщується ("піднімається") у верхню частину сфери, але foo = "f"частина залишається у вихідному місці. (Дивіться бідні неправильно зрозуміліvar в моєму анемічному маленькому блозі.)
letі constстанетьсяletі constвідрізняються між varсобою двома способами. Одним із питань, що стосується питання, є те, що хоча прив'язка, яку вони визначають, створюється до запуску будь-якого покрокового коду, вона недоступна, поки не буде досягнуто оператора letабо const.
Тому поки це працює:
display(a); // undefined
var a = 0;
display(a); // 0
Це призводить до помилки:
display(a); // ReferenceError: a is not defined
let a = 0;
display(a);
Решта два способи , якими letі constвідрізняються від var, які не є на самому справі відношення до питання, є:
varзавжди ставиться до всього контексту виконання ( в протягом глобального коду, або в протягом функціонального коду в функції , де вона з'являється), але letі constзастосовуються тільки в межах блоку , де вони з'являються. Тобто varмає функціональну (або глобальну) область застосування, але має letі constблок-сферу.
Повторення var aв тому ж контексті нешкідливо, але якщо у вас let a(або const a) let aвиникнення іншого або а const aчи а var aє синтаксичною помилкою.
Ось приклад, що демонструє це letі constнабуває чинності негайно в їхньому блоці перед запуском будь-якого коду в цьому блоці, але він не доступний до оператора letабо const:
var a = 0;
console.log(a);
if (true)
{
console.log(a); // ReferenceError: a is not defined
let a = 1;
console.log(a);
}
Зауважте, що другий console.logвиходить з ладу, замість того, щоб отримати доступ aіз зовнішнього блоку.
window)windowОб'єкт отримує дуже, дуже завалений властивостями. По можливості настійно рекомендую не додавати в безлад. Замість цього загортайте ваші символи в невеликий пакет і експортуйте щонайменше один символ до windowоб'єкта. (Я часто не експортую жодних символів до windowоб'єкта.) Ви можете використовувати функцію, щоб містити весь код, щоб містити ваші символи, і ця функція може бути анонімною, якщо вам потрібно:
(function() {
var a = 0; // `a` is NOT a property of `window` now
function foo() {
alert(a); // Alerts "0", because `foo` can access `a`
}
})();
У цьому прикладі ми визначаємо функцію і виконуємо її відразу ( ()в кінці).
Функція, що використовується таким чином, часто називається функцією масштабування . Функції, визначені в рамках функції масштабування, можуть отримати доступ до змінних, визначених у функції масштабування, оскільки вони закриваються над цими даними (див .: Закриття не є складним у моєму анемічному маленькому блозі).
window['a']=0зробити це зрозумілим, що я використовую вікно як карту? це windowособливий таким чином, що деякі браузери не дозволяють це і змусити мене використовувати window.a?
window.a = 0;працює лише в середовищі браузера і лише за умовами. Зв'язування глобального об'єкта в змінну з ім'ям windowне в ES Spec і тому не буде працювати, наприклад, V8 або Node.js, в той час як this.a = 0;(при виклику в глобальному контексті виконання) , буде працювати в будь-якому середовищі , оскільки специфікації дійсно вказати що має бути глобальний об'єкт. Якщо ви загортаєте свій код у IIFE, як у розділі Off-topic , ви можете передавати як параметр з ім'ям або отримати пряме посилання на глобальний об’єкт. thiswindowglobal
var a = 0;автоматично, стає властивістю глобального об'єкта. Якщо я оголошу var b = 0;в межах декларації функції, чи буде це також властивість якогось базового об'єкта?
Простіше:
a = 0
Код, наведений вище, дає глобальну змінну області
var a = 0;
Цей код дасть змінну, яка буде використана в поточній області та під нею
window.a = 0;
Зазвичай це те саме, що і глобальна змінна.
a під нинішній обсяг. Ти можеш. Крім того, ваше використання "глобальної змінної" трохи не вдається - два місця, які ви кажете "глобальна змінна", не є більш глобальними, ніж місце, про яке ви не говорите.
<title>Index.html</title>
<script>
var varDeclaration = true;
noVarDeclaration = true;
window.hungOnWindow = true;
document.hungOnDocument = true;
</script>
<script src="external.js"></script>
/* external.js */
console.info(varDeclaration == true); // could be .log, alert etc
// returns false in IE8
console.info(noVarDeclaration == true); // could be .log, alert etc
// returns false in IE8
console.info(window.hungOnWindow == true); // could be .log, alert etc
// returns true in IE8
console.info(document.hungOnDocument == true); // could be .log, alert etc
// returns ??? in IE8 (untested!) *I personally find this more clugy than hanging off window obj
Чи є глобальний об’єкт, за яким за замовчуванням вимкнено всі вар? наприклад: "globals.noVar заява"
window.*декларації. Ця декларація виглядає найбільш захищеною від копіювання коду, а також зрозумілою.
На основі чудової відповіді TJ Crowder : ( Off-topic: Уникайте захаращенняwindow )
Це приклад його ідеї:
Html
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="init.js"></script>
<script type="text/javascript">
MYLIBRARY.init(["firstValue", 2, "thirdValue"]);
</script>
<script src="script.js"></script>
</head>
<body>
<h1>Hello !</h1>
</body>
</html>
init.js (Виходячи з цієї відповіді )
var MYLIBRARY = MYLIBRARY || (function(){
var _args = {}; // private
return {
init : function(Args) {
_args = Args;
// some other initialising
},
helloWorld : function(i) {
return _args[i];
}
};
}());
script.js
// Here you can use the values defined in the html as if it were a global variable
var a = "Hello World " + MYLIBRARY.helloWorld(2);
alert(a);
Ось plnkr . Сподіваюся, це допоможе!
У глобальному масштабі немає смислової різниці.
Але вам слід справді уникати, a=0оскільки ви встановили значення для незадекларованої змінної.
Також використовуйте закриття, щоб уникнути редагування глобальної області застосування
(function() {
// do stuff locally
// Hoist something to global scope
window.someGlobal = someLocal
}());
Завжди використовуйте закриття та завжди піднімайтеся до глобальної сфери, коли це абсолютно необхідно. У більшості випадків ви повинні використовувати асинхронну обробку подій для більшості свого спілкування.
Як зазначав @AvianMoncellor, існує помилка IE, яка var a = fooлише оголошує глобальну область для файлу. Це проблема із сумнозвісною розбитою інтерпретацією IE. Ця помилка здається знайомою, тому, ймовірно, це правда.
Тож дотримуйтесь window.globalName = someLocalpointer
deleteможете var).
var. Вони просто абсолютно різні механізми, які мають практично однаковий практичний результат. :-)
varстрибає до зупинки сфери.