What is the difference between using var and this, in Javascript? - javascript

What is the difference between these?
var a = 13;
this.b = 21;
document.write(a);
document.write(b);

For global code (code that is not part of any function), they are almost equivalent, both at the end create a property on the global object.
The difference is that a, which has been declared with the var statement, the Variable Instantiation process will use the global object as the Variable Object (1), and it will define that property as non-deleteable on it, e.g.:
var a = 13;
delete a; // false
typeof a; // "number"
Then, b since the this value in global code, points to the global object itself, will be also a global property, but this one can be deleted:
this.b = 21;
delete b; // true
typeof b; // "undefined"
Don't try the first snippet in Firebug, since the Firebug's console runs the code internally with eval, and in this execution context the variable instantiation process behaves differently, you can try it here.
(1) The Variable Object (VO) is an object that is used by the variable instantiation process to define the identifiers of FunctionDeclarations, identifiers declared with the var statements, and identifiers of function formal parameters, in the different execution contexts, all those identifiers are bound as properties of the VO, the Scope chain is formed of a list of VO's.
For global code, the VO is the global object itself, that's why a ends being a property of it. For function code, the VO (also known as the Activation Object for FunctionCode), is a new object is created behind the scenes when you invoke a function, and that is what creates a new lexical scope, in short I'll talk about functions.
Both a and this.b can be resolved simply as by a and b because the first object in the scope chain, is again the global object.
Also, I think is work knowing that the Variable Instantiation process takes place before than the code execution, for example:
alert(a); // undefined, it exists but has no value assigned to it yet
alert(b); // ReferenceError is thrown
var a = 13;
this.b = 21;
These differences may be trivial but I think is worth knowing them.
Now, if the code snippet you posted is within a function, it is completely different.
The a identifier, declared with the var statement in your example will be a local variable, available only to the lexical scope of the function (and any nested functions).
Keep in mind that in JavaScript blocks don't introduce a new scope, only functions do, and to declare a variable in that scope, you should always use var.
The this.b identifier will become a property bound to the object that is referred by the this value, but... What is this???.
The this value in JavaScript is implicitly set when you call a function, it is determined by how do you invoke it:
When you use the new operator, the this value inside the function, will point to a newly created object, e.g.:
function Test() {
this.foo = "bar";
}
var obj = new Test(); // a new object with a `foo` property
When you call a function that is member of an object, the this value inside that function will point to the base object, e.g.:
var obj = {
foo: function () {
return this == obj;
}
};
obj.foo(); // true
When you invoke a function without any base object, the this value will refer to the global object:
function test() {
return this == window;
}
test(); // true
The this value can be set explicitly, when you invoke a function using call or apply:
function test() {
alert(this);
}
test.call("hello world!"); // alerts "hello world!"

To understand in short, if you use these in a function then -
this.a; //will create a public property
var b; //will create a member variable
e.g. here is a Student class in javascript
var Student = function()
{
// Member variable
var studentId;
// Public property
this.Name = "";
}
for more - See Object Oriented Programming with JavaScript

Related

If variables in the global context are properties, then how are they distinguished for the purposes of closures?

If variables in the global context are properties (on the global context), then how are they distinguished from other properties on the global context for the purposes of closures?
Obviously this doesn't work:
function foo() {
this.a = 'a';
this.bar = function() { console.log(a); }
}
new foo().bar(); // ReferenceError: a is not defined
Obviously this does work:
var a = 'a';
function bar() {
console.log(a);
}
bar(); // a
But how given that variable a is a "property". Where is my misunderstanding?
They are not distinguished - they are simply both a variable and a property. You might imagine that the global scope is the only scope object that is accessible as an actual language object.
The global environment consists of an environment record that is bound (like a with statement) to the global object, which itself is exposed as the window object in browsers.
To use your constructor example:
function Foo() {
with (this) {
this.a = 'a';
this.bar = function() { console.log(a); }
// Is `a` a variable or a property? It's *one* thing, available as both.
}
}
new Foo().bar(); // 'a'
Global scope is window object in Web browsers. Thus, a variable declaration in the global scope becomes a property of window.
// Somewhere in the global scope...
// Both declarations add a property to window
window.a = "hello world";
var a = "hello world";
In the other hand, when you add a property to an object using this keyword you're not adding it to the built-in window object. This is why the closure won't locate this.a as just a.
If you don't qualify a property name with this it's a variable that can be local or global - understanding global as a property of window object -.
JavaScript runtime looks for a variable in its current scope, otherwise in the parent scope, and so on, until it reaches global scope and, if window doesn't own a property - actually the variable identifier -, your browsers or any JavaScript runtime will determine that the variable is undefined.
In your first example, this.a is scoped to the this context of foo. If you change your code to this:
function foo() {
var a = 'a';
this.bar = function() { console.log(a); }
}
new foo().bar();
It will work. Otherwise you have to do this:
function foo() {
this.a = 'a';
this.bar = function() { console.log(this.a); }
}
new foo().bar();
The reason your first code example doesn't work is that:
console.log(a);
is looking for a variable named a in scope of the bar() method. But you have never declared such a variable. You've only declared a property on some other object with the name a. If you want to refer to that property, you have to use the appropriate object reference like this:
console.log(this.a);
All properties in Javascript MUST include the object that the property is on in order to access them except for properties on the global object which are treated as global variables. So, a is not the same thing as this.a in your context.
Variables are only global if they are declared in the global scope or explicitly attached to the global object (which is window in a browser) or if they are implicitly assigned to without declaration and you are not in strict mode (I call these accidental globals and consider them a horrible thing).
So, here are a couple things you could do.
Use a public instance variable:
function foo() {
this.a = 'a';
this.bar = function() { console.log(this.a); }
}
new foo().bar(); // outputs the member variable a
Or use a constructor local variable (essentially a private instance variable):
function foo() {
var a = 'a';
this.bar = function() { console.log(a); }
}
new foo().bar(); // outputs the member variable a
Or use an actual global (not recommended):
var a;
function foo() {
a = 'a';
this.bar = function() { console.log(a); }
}
new foo().bar(); // outputs the global a

Can I use function as an object inside the same function

I write the code as follows,
function Myfunction(){
Myfunction.myvar = "somevar";
}
After I execute the function, I can able to access Myfunction.myvar
How is it working? And If I do so, What is the problem hidden in this?
If any problem, please explain context of that.
Since the function does not execute until you call it, Myfunction.myvar is not evaluated immediately.
Once you call it, the function definition has been installed as Myfunction, so that it can be resolved when you do call it.
Something like the following would not work:
var x = {
foo: 1,
bar: x.foo } // x does not exist yet.
How is it working?
When you declare a function in some execution context, a binding is added to the variable environment of that context. When you reference an identifier, the current variable environment is checked to see if a binding exists for that identifier.
If no binding exists, the outer variable environment is checked, and so on, back up to the global scope.
So:
// OUTER SCOPE
// Binding exists for 'example'
function example() {
// INNER SCOPE
// No binding for 'example'
// References 'example' in outer scope
example.x = 1;
}
What is the problem hidden in this?
There are none (in general... although whether it's the right solution for you depends on what you're trying to do).
You are effectively creating a "static" property of the function. As JavaScript functions are first-class you can set properties on them as you would with any other object.
Note that the behaviour is different if you have a named function expression, rather than a function declaration:
var x = function example () {
// Identifier 'example' is only in scope in here
};
One problem you might get because of scoping, as a more complicate example shows:
function Other() {
console.log("a) Other.Myvalue",Other.Myvalue);
Other.Myvalue=typeof Other.Myvalue==='undefined' ? 0 : Other.Myvalue+1;
console.log("b) Other.Myvalue",Other.Myvalue);
}
Other();
Other();
this would lead to
a) Other.Myvalue undefined
b) Other.Myvalue 0
a) Other.Myvalue 0
b) Other.Myvalue 1
so you realy bind your variable Myvar to the function object itself which is a singleton and exists just once (and is created by the function definition itself in the current context which may be the global context), not to an instance of that object. But if you just use static values and don't need any logic, it's like the literal form, and I wouldn't expect any problems, other that the literal form is more convenient:
var Other = {
Myvalue: "somevalue"
};
In javascript every function is an object. So you can add any custom fields to it.
function A() {}
A.somevar = 'this is custom field';
A.prototype.somevar2 = 'this is field in A proto';
So when you will create new object with A contructor it will take properties from prototype.
var b = new A();
alert(b.somevar2);

Understanding privateness and scope of functions called as methods and as constructor in Javascript

Please consider the following code:
function Outer(){
function Inner(){
var private="something";
this.method = function(){
//some code here
};
}
var inner = new Inner(); //Why does this line not throw an error?
alert(inner.private); // not accessible here
inner.method();//no errors here
}
I am unable to understand why method() call doesn't throw an error and the variable reference throws an error? I understand that variables have their scope only within the function in which they are declared? But what about the scope of functions ?
There is nothing complicated about it and it has nothing to do with data types.
new Inner() creates a new object. You are assigning a property to that object in the constructor
this.method = function(){...};
On the other side, there is not such property private. You never do this.private = ...;. private is just a variable local to the Inner function.
Here is another example which is equivalent to your code but hopefully makes it clearer:
function createObject() {
var someVariable = '42';
var obj = {};
obj.foo = 'bar';
return obj;
}
var myObject = createObject();
// works, since we assigned the property to the object
console.log(myObject.foo);
// does not work, we never assigned such a property to the object
console.log(myObject.someVariable);
Inside createObject two variables are declared, someVariable and obj. obj is an object, we assign a property to it and return it from the function. someVariable has nothing to do with the object, but could be used for other purposes within the function.
The line var inner = new Inner() does throw an error as inner is not defined, it's only accessible within the body of the Outer function.
The inner.private is not accessible as a property of inner because it's a closure variable. So (new Inner()).private does not exist. (private seems to be a keyword in JS so I changed it to priv in sample code)
It is accessible within the Inner function body because code within the function body keeps a reference to closure variables.
function Inner(){
var priv="something";
this.method = function(){//wrong, should declare as prototype
console.log("private from within Inner function body:"
,priv)
};
}
var inner = new Inner();
console.log(inner.priv); //=undefined
inner.method();//=something
A function property of an object that will have many instances; like Inner can have many instances like: var a=new Inner(); var b = new Inner()... Should not be defined with this. You should use prototype instead.
When you use prototype you can't use private variables in the prototype functions because private (closure) variables are only accessible within the main function body. This is why many developers use _private or private_ to indicate it's private since JavaScript does not have a good way to make members private without messing up the prototype.
function Inner(){
var priv="private";//wrong
this._priv="private"
}
Inner.prototype.method=function(){
//cannot access priv
console.log(this._priv);//no problem
}
There is maybe one case where you can use privates in this way and that is when there is only one instance of your object.
var Mediator=(function(){
var events={};//private, other code can't mess this up
return{
addEvent:function(eventName){
events[eventName]=(events[eventName])?
events[eventName]:[];
},
addLisener:function(eventName,func){
events[eventName].push(func);
return events[eventName].length-1;
}
//more stuff like removeListener, trigger ...
}
})()
You can read about prototype in this basic example. You can run the code in Chrome or Firefox with firebug console. Press F12 to open it and paste the code from that link in the console. Then fiddle with it as you like and see if you get the expected output and understand prototyping in JS.

Javascript function with undefined parameter and the parameter is defined in function body , is a global variable?

let's suppose we have a javascript function and we want to check if the second parameter is undefined, in that case we want to assign it a value such as
function myFunc(a,b){
if(typeof b==="undefined" ){
b=0;
}
//do stuff
}
Does the variable b in the if block still refer to the function's parameter or a global variable named b is created?
Cheers
Yes, b gets resolved in the lexicalEnvironment (ES5) respectively Activation Object (ES3). It will always get resolved locally, even if a global variable b exists aswell by accessing the pure name.
You would need to explicitly call window.b respectively global.b (node) to access that global variable with the same name.
It refers to the function's parameter. You can test yourself like so:
var b = 45;
function myFunc(a,b){
if(typeof b==="undefined" ){
b=0;
}
alert( b ); //It will output 0
//do stuff
}
myFunc('');
The answers by #Andre and #Nelson are both correct, but just for clarity's sake:
var c = 123;
var func = (function(a)//a === 1234
{
var b = c;//local b === global c
return function(a,c)
{
console.log(c === b);//false, unless second argument was 123
console.log(a === 1234);//false, unless first arg was 1234
console.log('a masks the a of the outer scope');
};
})(1234);
JS will first scan the scope of the called function, for any vars used, if it doesn't find them there, it moves on to the outer scope. This can be another function, or, eventually, the global scope. In this example, the inner (returned) function will not be able to access the value of a as defined in the outer function. It's GC'ed when that outer function returned, because it's not being referenced anywhere.
code:
function myFunc(a,b){
if(typeof b==="undefined" ){
b=0;
}
console.log('b from myFunc:'+b)
}
myFunc(5);
console.log('global:'+b)
output:
b from myFunc:0
b is not defined
Javascript first looks in the local scope for either a local variable or a named function argument. If it finds the symbol there, then that variable is the one that is used.
Only if a matching local symbol is not found is a global symbol used.
Thus, in your example, you will be setting the value of b the function argument.
Once you've defined a local symbol in either a local variable or a named function argument, you can no longer use that name by itself to access a global variable of the same name. If you specifically want to address the global variable, you can do so by prefixing it with window. as in window.b. This specifically targets the global scope so the local scope is not used.
The variable stays on the function if;
the variable is declared inside the function using var or without it
the variable is declared with this as it's parent node the function, example below
function foo(){
this.bar = 'hello';
}
the variable becomes available in the global scope when
the variable is declared outside any function using var or without it
the variable is declared as it's parent node is window example below
window.bar ='i am global'
YOU NEED DEFINE VARIABLE GLOBALLY :
In the below code t2 is undefined.
<script>
var t1="";
var t2;
function check(t1,t2){
if (t1===undefined)
{
alert("t1 is undefined");
}
if (t2===undefined)
{
alert("t2 is undefined");
}
}
</script>
REF :
http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_undefined

JavaScript global object?

Does the value of "this" refer to the global object or the object "o" in the program below?
More importantly, what code could I run to test what the reference of "this" is?
function F() {
function C() {
return this;
}
return C();
}
var o = new F();
It refers to the global object (window).
Edit: Actually, it will refer to both, the global object and o, because they are the same. o will have a reference to the object returned from F() which is the object returned from C() which is the window object ;)
You can call console.log(this) to find out which object it refers to. It should give you a listing of all the methods of the object on the console and you should be able to infer from this which object it is.
For this to work in Firefox, you need Firebug. Don't know for IE.
Update:
#Anurag already showed you how to explicitly set this. If you just want to refer to this of a higher scope, you have to assign it to a variable explicitly. Example:
function F() {
var that = this;
function C() {
console.log(that);
}
C();
}
this refers to the global object in your program. To get this to reference the instance of F, try,
function F() {
function C() {
return this;
}
return C.call(this); // call C with the object of F as a context
}
var o = new F();
On Chrome, you could simply enter the variable to inspect, and its value will get logged. It's similar to doing a console.log(object), but much easier to work with. Here's a screenshot of running this code sample in Chrome. The value of the last statement o is automatically printed, and I printed it once again, just to be sure. It logged DOMWindow which refers to the global window object on the browser.
To add to the other answers:
When a function is called, this is set depending on how it's called. If it's called with myfunc.call or myfunc.apply, then this is set to the first passed argument. If it's called in the 'dotted' form, i.e. myObject.myfunc() then this is set to whatever is before the dot.
There is an exception to this rule, which is that it's possible to bake the value of this in with bind, in which case it will be whatever has been bound. i.e. in var boundfunc = myfunc.bind(myobj); then any time boundfunc is called, it would be like calling myfunc but with this referring to myobj regardless of anything else. Here's an example that does that:
function F() {
var C = function() {
return this;
}.bind(this);
return C();
}
var o = new F();
If none of these cases are applicable, then this is always either the global object (window if you're in a browser), or, if you're in strict mode it's undefined.

Categories