Difference between variable declaration syntaxes in Javascript (including global variables)? -
is there difference between declaring variable:
var a=0; //1 ...this way:
a=0; //2 ...or:
window.a=0; //3 in global scope?
yes, there couple of differences, though in practical terms they're not big ones.
there's fourth way, , of es2015 (es6) there's 2 more. i've added fourth way @ end, inserted es2015 ways after #1 (you'll see why), have:
var = 0; // 1 let = 0; // 1.1 (new es2015) const = 0; // 1.2 (new es2015) = 0; // 2 window.a = 0; // 3 this.a = 0; // 4 those statements explained
#1 var = 0;
this creates global variable property of global object, access window on browsers (or via this global scope, in non-strict code). unlike other properties, property cannot removed via delete.
in specification terms, creates identifier binding on object environment record global environment. makes property of global object because global object identifier bindings global environment's object environment record held. why property non-deletable: it's not simple property, it's identifier binding.
the binding (variable) defined before first line of code runs (see "when var happens" below).
note on ie8 , earlier, property created on window not enumerable (doesn't show in for..in statements). in ie9, chrome, firefox, , opera, it's enumerable.
#1.1 let = 0;
this creates global variable not property of global object. new thing of es2015.
in specification terms, creates identifier binding on declarative environment record global environment rather object environment record. global environment unique in having split environment record, 1 old stuff goes on global object (the object environment record) , new stuff (let, const, , functions created class) don't go on global object.
the binding created before step-by-step code in enclosing block executed (in case, before global code runs), it's not accessible in way until step-by-step execution reaches let statement. once execution reaches let statement, variable accessible. (see "when let , const happen" below.)
#1.2 const = 0;
creates global constant, not property of global object.
const let except must provide initializer (the = value part), , cannot change value of constant once it's created. under covers, it's let flag on identifier binding saying value cannot changed. using const 3 things you:
- makes parse-time error if try assign constant.
- documents unchanging nature other programmers.
- lets javascript engine optimize on basis won't change.
#2 a = 0;
this creates property on global object implicitly. it's normal property, can delete it. i'd recommend not doing this, can unclear reading code later.
and interestingly, again on ie8 , earlier, property created not enumerable (doesn't show in for..in statements). that's odd, particularly given #3 below.
#3 window.a = 0;
this creates property on global object explicitly, using window global refers global object (on browsers; non-browser environments have equivalent global variable, such global on nodejs). it's normal property, can delete it.
this property is enumerable, on ie8 , earlier, , on every other browser i've tried.
#4 this.a = 0;
exactly #3, except we're referencing global object through this instead of global window. won't work in strict mode, though, because in strict mode global code, this doesn't have reference global object (it has value undefined instead).
deleting properties
what mean "deleting" or "removing" a? that: removing property (entirely) via delete keyword:
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 removes property object. can't properties added window indirectly via var, delete either silently ignored or throws exception (depending on javascript implementation , whether you're in strict mode).
warning: ie8 again (and presumably earlier, , ie9-ie11 in broken "compatibility" mode): won't let delete properties of window object, when should allowed to. worse, throws exception when try (try experiment in ie8 , in other browsers). when deleting window object, have defensive:
try { delete window.prop; } catch (e) { window.prop = undefined; } that tries delete property, , if exception thrown next best thing , sets property undefined.
this only applies window object, , (as far know) ie8 , earlier (or ie9-ie11 in broken "compatibility" mode). other browsers fine deleting window properties, subject rules above.
when var happens
the variables defined via var statement created before any step-by-step code in execution context run, , property exists before var statement.
this can confusing, let's take look:
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" live example:
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" function display(msg) { var p = document.createelement('p'); p.innerhtml = msg; document.body.appendchild(p); } as can see, symbol foo defined before first line, symbol bar isn't. var foo = "f"; statement is, there 2 things: defining symbol, happens before first line of code run; , doing assignment symbol, happens line in step-by-step flow. known "var hoisting" because var foo part moved ("hoisted") top of scope, foo = "f" part left in original location. (see poor misunderstood var on anemic little blog.)
when let , const happen
let , const different var in couple of ways. way that's relevant question although binding define created before step-by-step code runs, it's not accessible until let or const statement reached.
so while runs:
display(a); // undefined var = 0; display(a); // 0 this throws error:
display(a); // referenceerror: not defined let = 0; display(a); the other 2 ways let , const differ var, aren't relevant question, are:
varapplies entire execution context (throughout global code, or throughout function code in function appears),let,constapply within block appear. is,varhas function (or global) scope,let,consthave block scope.repeating
var ain same context harmless, if havelet a(orconst a), havinglet aorconst aorvar asyntax error.
here's example demonstrating let , const take effect in block before code within block runs, aren't accessible until let or const statement:
var = 0; console.log(a); if (true) { console.log(a); // referenceerror: not defined let = 1; console.log(a); } note second console.log fails, instead of accessing a outside block.
off-topic: avoid cluttering global object (window)
the window object gets very, cluttered properties. whenever possible, recommend not adding mess. instead, wrap symbols in little package , export @ most 1 symbol window object. (i don't export any symbols window object.) can use function contain of code in order contain symbols, , function can anonymous if like:
(function() { var = 0; // `a` not property of `window` function foo() { alert(a); // alerts "0", because `foo` can access `a` } })(); in example, define function , have executed right away (the () @ end).
a function used in way called scoping function. functions defined within scoping function can access variables defined in scoping function because they're closures on data (see: closures not complicated on anemic little blog).
Comments
Post a Comment