for example, my code below
(function ($) {
window.FOO || (FOO = {});
}(jQuery));
caused jshint error:
Expected an assignment or function call and instead saw an expression.
Are there any better way to write my above code?
i.e. if FOO is not defined in global window scope, init it as {}
Update: From comments:
I've updated the code above. I want the FOO in the global scope, i.e. window.
For that you can just set window.FOO instead:
window.FOO = window.FOO || {};
Here if window.FOO already exists its value will remain unchanged, otherwise window.FOO will be set to an empty object.
Old answer:
You need to declare the variable using var:
var FOO = window.FOO || {};
This will set the FOO variable to window.FOO if that exists or an empty object if not.
var FOO = window.FOO || {};
console.log(FOO);
> Object {}
window.FOO = "Hello, world!";
var FOO = window.FOO || {};
console.log(FOO);
> "Hello, world!"
Related
As I understand the scope of const is curly braces (block). However, when I run the following code in browser (FF) it doesn't give any error. Is the following JS code right? Please, explain.
<script type="text/javascript">
{
const Foo = "foo";
}
</script>
<div></div>
<script type="text/javascript">
{
Foo = null;
}
</script>
You will not get error because,
Below code says you are using const variable of Foo inside this code block, the const Foo will bot be accessible out side of the block
{
const Foo = "foo";
}
Below code says you are assigning the variable Foo with value of null, which will bind to window object,
{
Foo = null;
}
so Foo = null; which binds to window object and const Foo='foo' is a constant variable for the particular code block
So when you are assign Foo=null it assigns the variable to window object and you can access it like ,
window.Foo
i.e. any variable which declare without var it will bind to window object,
You are aware that using const will create a constant in a given scope. Look at your example:
<script type="text/javascript">
{
const Foo = "foo";
}
</script>
<div></div>
<script type="text/javascript">
{
Foo = null;
}
</script>
You can reduce the above to the following code:
{
const Foo = "foo";
}
{
Foo = null;
}
Since you have declared and initialized Foo in a scope (denoted by using { and }), then Foo is only known to that scope. Let's call that scope A. When issuing Foo = null;, you are in a different scope: B. When assigning a value to a variable, the engine always checks if the variable name is not bound in the current execution context. In short, it checks
if Foo exists in the local scope: the answer is no. Your Foo = "foo" is only known to the scope A. Not in the current scope.
if Foo exists in the scope chain: the answer is no. There is no declarations made in the parent scope.
if Foo is known to the global execution context (aka window scope): the answer is no.
End result: the assignment will occur. But since you did not have provided any assignment statements: const, let or var. Therefore, Foo=null will be added to the window scope. If you do window.Foo, you will get a response with null.
However, it has to be noted that there should be an error. But Javascript is a language that "serves" the developer. Instead of spitting you with an error, it will silent that error and hook Foo to the window object. If you use strict mode, then it will throw an error. (please consult the MDN page for further information)
To comprehend it a better, look to the following examples that is executed in a non-strict environment and think first if there would be an error or not.
<script type="text/javascript">
{
const Foo = 'hello';
Foo = 555; // success or fail ?
}
</script>
The answer is no. You are aware of that. It fails the first check: Foo is already bound in the same scope.
<script type="text/javascript">
{
const Foo = 'hello';
{
Foo = 555; // success or fail ?
}
}
</script>
The answer is yes. It will fail because it fails the second check (see the list above). Foo = 555; is called in a scope: B. Scope B has a parent scope: A where Foo is known.
Now, something tricky:
<script type="text/javascript">
{
window.Foo = 'hello';
{
Foo = 555; // success or fail ?
}
}
</script>
What do you think? 🙂
...
it works. Do you not believe me: check it here below:
{
window.Foo = 'hello world';
console.log('window.Foo?', window.Foo); // shows hello world
{
Foo = 555;
console.log('window.Foo?', window.Foo); // shows 555
}
}
that is because adding variables to the window scope (although it is not recommendable to do so) does not make it read-only. You can change it afterwards as desired.
Does this produce the same results? What if function foo does not exist?
var foo = foo || function(){
console.log("I'm Batman");
}
vs
var foo = function() {
console.log("I'm Batman")
}
It's a way of declaring foo if and only if it has not already been declared in some other scope. If it has, then the new, more local foo shall be identical to the broader one.
It works because of what || does and because foo is undefined if it's not, um, defined.
The whole thing is pretty rare, though, and not one of the usual ways to declare a function.
It is known as guard operator ... one feature of javascript
x = a || b;
// if the first is true will return the first. Else will return the second;
Look more about in this question:
Javascript || operator
Hope it helps..
The code does this (more or less):
If foo was not declared in the current scope, it declares it and sets its value to undefined. If it's already declared, it remains declared with the same value.
It checks if the value of foo is truthy.
If it's truthy, the value of foo is not changed
If it's falsy, foo is overwritten with the new value.
Therefore
If foo was not declared in the current scope, it is declared, and the new value is assigned.
var foo = 123; // Another scope
(function() {
var foo = foo || 'abc';
foo; // 'abc'
})();
If foo was declared in the current scope and its value was falsy, foo is overwritten with the new value.
var foo = ''; // Same scope, falsy value
var foo = foo || 'abc';
foo; // 'abc'
If foo was declared in the current scope and its value was truthy, foo is not altered.
var foo = 123; // Same scope, truthy value
var foo = foo || 'abc';
foo; // 123
One of my friends was taking an online quiz and he asked me this question which I could not answer.
var global = false;
function test() {
global = true;
return false;
function global() {}
}
console.log(global); // says false (As expected)
test();
console.log(global); // says false (Unexpected: should be true)
If we assume that functions are hoisted at the top along with var variables, let's try this one.
var foo = 1;
function bar() {
return foo;
foo = 10;
function foo() {}
var foo = 11;
}
bar();
console.log(foo); //says 1 (But should be 11) Why 1 this time ??
Here is a JSBin Demo and JSBIN Demo2 to play with.
PS: If we remove function global() {} from test(), then it runs fine. Can somebody help me understand why is this happening ?
var statements and function declaration statements are "hoisted" to the top of their enclosing scope.
Therefore, the function global(){} in your function creates a local global name.
Assigning to global inside your functions binds to this local name. Here's how you can "rewrite" it using hoisting to understand how the compiler sees it:
function test() {
var global = function() {}; // hoisted; 'global' now local
global = true;
return false;
}
I'll answer the second part of your question,
If we assume that functions are hoisted at the top along with var variables
bar();
console.log(foo); //says 1 (But should be 11) Why 1 this time ??
You should try console.log(bar()); console.log(foo); instead. However, what hoisting does to your function is this:
function bar() {
var foo;
function foo() {}
return foo;
foo = 10;
foo = 11;
}
So you should expect to get the function returned, since your variable assignments are after the return statement. And both the var and the function declaration make foo a local variable, so the global foo = 1 is never changed.
Newbie to JavaScript here.
How do I reference member foo from within member foobar, given that foobar's in a closure?
var priv = {
foo: "bar",
foobar: (function() {
return this.foo === "bar";
})()
};
The code above fails. In it, this.foo is undefined. If I change this.foo to priv.foo, it's still undefined. How do I reference priv.foo from within the foobar closure?
It's impossible to read any properties of an object in its defination during its initialization since prev will be undefined at that time.
When you're trying to call a clojure inside it, it refers to undefined this or priv.
Probably you wanted to write:
foobar: (function() {
return this.foo === "bar";
})
without () in the end. And then you could call it as priv.foobar();
If you still need to call it, you could define foobar after foo:
var priv = {
foo: "bar"
};
priv.foobar = (function() {
return priv.foo === "bar";
})()
The problem is that you aren't defining a closure - I don't think that there is any way to access foo from your function as priv is not yet initialised.
What exactly are you trying to do? The following is equivalent to what I understand your sample is trying to do, but my guess is that I'm not understanding the problem:
// Set elsewhere
var foo = "bar";
var priv = {
foo: foo ,
foobar: foo == "bar"
};
What is the difference between declaring a variable with this or var ?
var foo = 'bar'
or
this.foo = 'bar'
When do you use this and when var?
edit: is there a simple question i can ask my self when deciding if i want to use var or this
If it is global code (the code is not part of any function), then you are creating a property on the global object with the two snippets, since this in global code points to the global object.
The difference in this case is that when the var statement is used, that property cannot be deleted, for example:
var foo = 'bar';
delete foo; // false
typeof foo; // "string"
this.bar = 'baz';
delete bar; // true
typeof bar; "undefined"
(Note: The above snippet will behave differently in the Firebug console, since it runs code with eval, and the code executed in the Eval Code execution context permits the deletion of identifiers created with var, try it here)
If the code is part of a function you should know that the this keyword has nothing to do with the function scope, is a reserved word that is set implicitly, depending how a function is called, for example:
1 - When a function is called as a method (the function is invoked as member of an object):
obj.method(); // 'this' inside method will refer to obj
2 - A normal function call:
myFunction(); // 'this' inside the function will refer to the Global object
// or
(function () {})();
3 - When the new operator is used:
var obj = new Constructor(); // 'this' will refer to a newly created object.
And you can even set the this value explicitly, using the call and apply methods, for example:
function test () {
alert(this);
}
test.call("hello!"); //alerts hello!
You should know also that JavaScript has function scope only, and variables declared with the var statement will be reachable only within the same function or any inner functions defined below.
Edit: Looking the code you posted to the #David's answer, let me comment:
var test1 = 'test'; // two globals, with the difference I talk
this.test2 = 'test'; // about in the beginning of this answer
//...
function test4(){
var test5 = 'test in function with var'; // <-- test5 is locally scoped!!!
this.test6 = 'test in function with this'; // global property, see below
}
test4(); // <--- test4 will be called with `this` pointing to the global object
// see #2 above, a call to an identifier that is not an property of an
// object causes it
alert(typeof test5); // "undefined" since it's a local variable of `test4`
alert(test6); // "test in function with this"
You can't access the test5 variable outside the function because is locally scoped, and it exists only withing the scope of that function.
Edit: In response to your comment
For declaring variables I encourage you to always use var, it's what is made for.
The concept of the this value, will get useful when you start working with constructor functions, objects and methods.
If you use var, the variable is scoped to the current function.
If you use this, then you are assigning a value to a property on whatever this is (which is either the object the method is being called on or (if the new keyword has been used) the object being created.
You use var when you want to define a simple local variable as you would in a typical function:-
function doAdd(a, b)
{
var c = a + b;
return c;
}
var result = doAdd(a, b);
alert(result);
However this has special meaning when call is used on a function.
function doAdd(a, b)
{
this.c = a + b;
}
var o = new Object();
doAdd.call(o, a, b);
alert(o.c);
You note the first parameter when using call on doAdd is the object created before. Inside that execution of doAdd this will refer to that object. Hence it creates a c property on the object.
Typically though a function is assigned to a property of an object like this:-
function doAdd(a, b)
{
this.c = a + b;
}
var o = new Object();
o.doAdd = doAdd;
Now the function can be execute using the . notation:-
o.doAdd(a, b);
alert(o.c);
Effectively o.doAdd(a, b) is o.doAdd.call(o, a, b)
var foo = 'bar'
This will scope the foo variable to the function wrapping it, or the global scope.
this.foo = 'bar'
This will scope the foo variable to the this object, it exactly like doing this:
window.foo = 'bar';
or
someObj.foo = 'bar';
The second part of your question seems to be what is the this object, and that is something that is determined by what context the function is running in. You can change what this is by using the apply method that all functions have. You can also make the default of the this variable an object other than the global object, by:
someObj.foo = function(){
// 'this' is 'someObj'
};
or
function someObj(x){
this.x=x;
}
someObj.prototype.getX = function(){
return this.x;
}
var myX = (new someObj(1)).getX(); // myX == 1
In a constructor, you can use var to simulate private members and this to simulate public members:
function Obj() {
this.pub = 'public';
var priv = 'private';
}
var o = new Obj();
o.pub; // 'public'
o.priv; // error
Example for this and var explained below:
function Car() {
this.speed = 0;
var speedUp = function() {
var speed = 10; // default
this.speed = this.speed + speed; // see how this and var are used
};
speedUp();
}
var foo = 'bar'; // 'var can be only used inside a function
and
this.foo = 'bar' // 'this' can be used globally inside an object