I've attached an animated gif to illustrate this weird behavior. Essentially, my question is does Chrome console treat var and let differently when used in the same scope? You'll notice that after declaring / assigning a variable, if you try to type that variable's name into the console, Chrome will autocomplete it for you, showing a dropdown list containing what your typing. When using lets, this is not the case. Is this a bug, feature, or is there something I'm missing about var and let in JavaScript?
Note: I'm well aware that let lives & dies within the immediate scope.
When you use var in the console, it executes in the global scope and adds the variable to the window object.
When you use let in the console, it executes in the global scope, which doesn't add the variable to the window object.
When you start typing, autocomplete checks the parent object for properties to complete along with other language constructs, such as function, for, and while.
When there is no content in the console, the parent object is window, which won't have the property you're looking for because let doesn't add the property to window.
As soon as you have a new object for autocomplete to complete, behavior returns to what you'd expect.
> let foo = {bar: 'baz'};
> foo.b //autocompletes bar
Now, with all of that said, there's no reason that autocomplete has to behave that way. In many regards the lack of autocomplete for variables defined in global scope via let could be considered a "bug" worth "fixing". In my opinion it is moderately surprising behavior.
var defines a variable on the global scope, while let defines it only in the local scope. Most likely, the autocomplete is only looking on the global scope for targets.
Related
(Sorry for my poor English)
I finally realized why it's better to use let or const instead of var because var can't work with window properties!
However, is it a good idea still to use window properties as variable names just because you can bypass the problem by using other two keywords of creating variables?
For example:
var name = 'James';
console.log(name);
The above won't work because I'm using var keyword however if I used let or const, this wouldn't cause any error!
So once again, just because I can should I ?
Using variable names that exist as properties on the window object was never the real problem. Using them for global variables was (and still is). But if you are in a local scope, e.g. inside a function, you can name your local variables however you like.
If you cannot avoid global variables, you should strife to use as few as possible, and yes you should try to avoid collisions with other globals, be they properties of window or not. Using let or const just ensures that if they are window properties, your custom variable will shadow them, but you will still break other code that relies on these to be accessible as global variables with the builtin value. However, most of the time you cannot avoid global variables you also cannot avoid var, as let and const cannot be redeclared.
var
Function-scoped variable. It is visible in the current function. If it's outside all functions, then it's visible globally, assuming it's not in module scope.
let
Block-scoped variable. It's visible in the {} block where it was defined.
const
Block-scoped constant. Like let, it's block-scoped, but this one is constant.
object property
window is an object, so let's think about objects in general.
window.foo = "bar"; console.log(window.foo);
"Better"
One is not "better" than the other by definition. You will need to think about your needs and the conventions your team has agreed upon and apply them. Setting window attributes should not be a custom in general, because you are making it global, but sometimes you need to set window properties. Again: always think about what you need to achieve.
Can anyone tell me the difference between these? I started noticing some behaviours that i was not expecting.
let myObj = { _name:"Consala",
get name(){
return `Mr. ${this._name}` }}
Why does this require the this keyword because i thought functions have access to all variables surrounding them.
I explained this by saying that variables are different from properties and there is no variable called _name inside of the myObj just a property. Im not sure if this is correct though.
I tried to test this theory using this:
let test = "banana"
print(test) //prints banana
print(this.test) //prints undefined
this.test = "apple"
print(this.test) //prints apple
I thought this confirmed what i thought because when undefined was printed i explained it as there is no property called test on the global object showing me there is a difference between variables and properties.
But then i changed let to var and then print(this.test) also prints banana instead of undefined...
Whats going on here?
Im pretty confused but im thinking that when you use var you are setting a property to the object its in (which would explain why var has function scope right?) but then what happens when you use let?
**I hope people dont think of this as a low effort post because i have really been trying to figure this one out on my own rather than just refusing to think for myself. Cheers
The reason why var prints banana instead of undefined is because you have declared it outside of all functions so it takes global scope.
The scope of a variable declared with var is its current execution context and closures thereof, which is either the enclosing function and functions declared within it, or, for variables declared outside any function, global.
Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
On the other hand, let is block scoped so it gives you undefined
And to answer your question about why we need this, it is because the name getter function has no variable called _name in its scope.
Thus it needs this to indicate to it to use the object scope to look for the _name variable
this keyword is the most confusing keyword in JavaScript. It's not because it's kind of buggy or what but it's because developers think it will work in the same way as it does in other languages but that's not true.
this has dynamic scope. Dynamic scoping does not care how the code is written, but instead how it executes. So the value of this depends on how is it executed.
Talking about your first example
let myObj = { _name:"Consala",
get name(){
return `Mr. ${this._name}` }}
In this case, when you call that function you type myObj.name which binds myObj as this to name. So whenever you call a function using [Object Name].[function] you assign this object as the function's this.
Let's come to the second scenario. I assume you tried that in your browser.
In the case of Browser, this refers to window Object (Try console.log(this) ).
What happens there is when you declare a variable using let it doesn't add to Window object but when you declare it using var keyword, it adds to Window Object.
Try declaring a Variable using var and then do console.log(this). You will find that variable in Window Object but in case of a variable declared using let won't be there.
Have you ever taken a look under the hood at the jQuery 1.4 source code and noticed how it's encapsulated in the following way:
(function( window, undefined ) {
//All the JQuery code here
...
})(window);
I've read an article on JavaScript Namespacing and another one called "An Important Pair of Parens," so I know some about what's going on here.
But I've never seen this particular syntax before. What is that undefined doing there? And why does window need to be passed and then appear at the end again?
The undefined is a normal variable and can be changed simply with undefined = "new value";. So jQuery creates a local "undefined" variable that is REALLY undefined.
The window variable is made local for performance reasons. Because when JavaScript looks up a variable, it first goes through the local variables until it finds the variable name. When it's not found, JavaScript goes through the next scope etc. until it filters through the global variables. So if the window variable is made local, JavaScript can look it up quicker.
Further information: Speed Up Your JavaScript - Nicholas C. Zakas
Undefined
By declaring undefined as an argument but never passing a value to it ensures that it is always undefined, as it is simply a variable in the global scope that can be overwritten. This makes a === undefined a safe alternative to typeof a == 'undefined', which saves a few characters. It also makes the code more minifier-friendly, as undefined can be shortened to u for example, saving a few more characters.
Window
Passing window as an argument keeps a copy in the local scope, which affects performance: http://jsperf.com/short-scope. All accesses to window will now have to travel one level less up the scope chain. As with undefined, a local copy again allows for more aggressive minification.
Sidenote:
Though this may not have been the intention of the jQuery developers, passing in window allows the library to be more easily integrated in server-side Javascript environments, for example node.js - where there is no global window object. In such a situation, only one line needs to be changed to replace the window object with another one. In the case of jQuery, a mock window object can be created and passed in for the purpose of HTML scraping (a library such as jsdom can do this).
Others have explained undefined. undefined is like a global variable that can be redefined to any value. This technique is to prevent all undefined checks from breaking if someone wrote say, undefined = 10 somewhere. An argument that is never passed is guaranteed to be real undefined irrespective of the value of the variable undefined.
The reason to pass window can be illustrated with the following example.
(function() {
console.log(window);
...
...
...
var window = 10;
})();
What does the console log? The value of window object right? Wrong! 10? Wrong! It logs undefined. Javascript interpreter (or JIT compiler) rewrites it this way -
(function() {
var window; //and every other var in this function
console.log(window);
...
...
...
window = 10;
})();
However, if you get the window variable as an argument, there is no var and hence no surprises.
I don't know if jQuery is doing it, but if you are redefining window local variable anywhere in your function for whatever reason, it is a good idea to borrow it from global scope.
window is passed in like that just in case someone decides to redefine the window object in IE, I assume the same for undefined, in case it's re-assigned in some way later.
The top window in that script is just naming the argument "window", an argument that's more local that the global window reference and it what the code inside this closure will use. The window at the end is actually specifying what to pass for the first argument, in this case the current meaning of window...the hope is you haven't screwed up window before that happens.
This may be easier to think of by showing the most typical case used in jQuery, plugin .noConflict() handling, so for the majority of code you can still use $, even if it means something other than jQuery outside this scope:
(function($) {
//inside here, $ == jQuery, it was passed as the first argument
})(jQuery);
Tested with 1000000 iterations. This kind of localization had no effect in performance. Not even a single millisecond in 1000000 iterations. This is simply useless.
I need to emulate in firefox the behavior of activeXobject in last versions of ie. I write addon with contentScript and want to implement to pages such variable. It is exactly what I want - It is a challenge in itself.
Example of IE 11 working code:
if (window.ActiveXObject == undefined) {
var but = new window.ActiveXObject; // [ActiveXObject object]
}
I need exactly same behavior in firefox with my variable
For example what i want
<script>
console.log(window.variable) // undefined
console.log(new window.variable); // [object Variable]
console.log(new variable) // [object Variable] if not possible previous string
</script>
for solving, you can change the addon sdk or a browser source, change realization of all getters or something else
In browser Javascript, there is no such thing as a global variable that is not a property of the window object. So, if that's truly what you are trying to do, then it cannot be done. Yes, you might be able to create a getter on the window object with Object.defineProperty(), but that's still a property on the window object so I'm not sure how that helps you.
Likewise, there is no structure in Javascript such that:
window.ActiveXObject === undefined
and this works:
var x = new window.ActiveXObject;
Javascript just simply doesn't work that way. The property either exists or it doesn't. It can't be undefined for one way of accessing it and defined for some other way of accessing it.
You might also be able to create the property on the window object so it is not enumerable if you want it to be less visible for some reason.
If you explained what you're really trying to accomplish, there may be some work-arounds by enclosing the relevant code in a closure and defining the variable in the closure, but without knowing more details about what the actual problem to be solved is, we can't help more specifically than that.
If you just want the variable defined for YOUR code only, then you can just put it in a closure:
(function() {
var myVar = "foo";
// other parts of your code
// elsewhere in your code
console.log(myVar);
})();
Your code can treat it like a global, but it's really not a global, it's just defined within the scope that your code lives and not available to any other code outside this scope.
Theoretically, this is possible with lexically declared variables in ES6:
let variable = 5;
console.log(variable); // 5
console.log(window.variable) // undefined
However, the current let support in FF is not as advanced, and still treats this a property of the global object.
If the variable only needs to be accessible by your project code, wrap all of your project code in a self executing anonymous function.
(function(){
var internalGlobalVar = "some value";
//All your code gets wrapped in here...
})();
Then if you tried to alert(window.internalGlobalVar) you would get undefined.
We use google closure compiler with plovr and wrap all of our code in a self executing anonymous function so basically all of our global variables are project scope, not on the window "output-wrapper": "(function($){%output%})(jQuery);"
First time poster. I tried to search for answer before posting.
I'm new to javascript, coming from a Delphi/pascal background. I am used to things having to be explicitly spelled out. When I see code that includes setTimeout or setInterval (see here:
http://www.w3schools.com/js/tryit.asp?filename=tryjs_setinterval1), I notice that it just looks like an intrinsic function. But I think it is actually a method of the Windows object.
So it looks like the "window." part is optional. Is this somethign specific to the Window object? Or will any method that is specified without the name of it's containing object be recognized in javascript? And what would happen if there was another variable in the global scope that had a method also named setTimeout? How would the compiler/interpreter know which one to use?
Thanks so much,
Kevin
In Javascript, there is something called the Global scope. On Browsers, the global scope object is window. If you create a variable outside of a function, it goes by default into the global scope, which is window.
When invoking a method or referencing a variable on the window object, it's optional to include window.
its not windows its window (no 's' at end).
As far as i know javascript have 3 scopes local, [clouser], global
Every variable or function is first looked up in local scope, then clouser and finally if not found anywhere in between it will checked in global scope.
As in image you will see global scope is shown as Window object which mean whatever goes in global scope goes in window object.
copy paste below code in chrome devtools console
function outerFunction() {
var a = 10;
debugger;
function innerFunction() {
'use strict';
var b = 10;
debugger;
console.log(a);
}
innerFunction();
}
outerFunction();
on 1st debug
on 2nd debug