I have three simple programs below with different outputs. I am a bit confused as to why I get a different output. What really happens when you assign a function to a variable? Does it not run unless you have parentheses (i.e. myfunction())? I'm also very confused as to how JavaScript allows the parenthesis behind a function as 'optional' when calling it. Can someone clear this up? I only know Java so this is all new territory for me.
// ------First--------------------------------
var x = 9;
function myfunction (){
x = 3;
}
var w = myfunction;
w();
console.log(x);
//output is 3
// ---------Second -----------------------------
var x = 9;
function myfunction (){
x = 3;
}
var w = myfunction;
console.log(x);
//output is 9
// ---------Third -----------------------------
var x = 9;
function myfunction (){
x = 3;
}
var w = myfunction();
console.log(x);
//output is 3
No, it does not. A reference to a function by name is simply a reference to a value, like any other value. Without the () operator, it's not a function call.
Parentheses are not optional when calling a function except when it's being called via the new operator. Thus:
function foo() {
console.log("hi!");
}
var otherFoo = foo; // no function call
var obj = new foo; // function call via "new"
var x = foo(); // function call via "()"
Related
Shouldn't the value of research be undefined as it has been declared as var research in the end. And hence the output be a type error. But I am getting the output as 'hello'. Any idea why?
function newFunc() {
function research() { console.log('hello') };
research();
var research;
}
newFunc();
Because of hoisting, what actually happens is more like this:
function newFunc() {
var research;
research = function() { console.log('hello') };
research();
}
newFunc();
The variable declarations and function definitions are hoisted - moved to the top of the function scope. So even though you are declaring it at the end, the compiler will move it to the top of the function so it ends up like:
function newFunc() {
var research = function () { console.log('hello') };
research();
}
newFunc();
JS only hoists declarations, not initializations. JS also hoists the actual function definition.
JavaScript only hoists declarations, not initializations. Documentation
So values will be assigned in the order they are placed, for instance:
x = 2;
console.log(x); //2
x = 3;
console.log(x); //3
var x ;
or in your case:
var x = 2;
console.log(x); //2
var x = 3;
console.log(x); //3
var x ;
Another thing is that, research in the var research; part is not undefined; it's rather a function expression till you override it by another assignment, like var research = '';
So in your case, it's like the following:
function newFunc() {
function research() { console.log('hello') };
research(); //'hello'
var research;
console.log(research) //function research(){console.log('hello');}
}
For example:
(function foo() {
var a = 3;
console.log(a);
});
var obj = {
a: (function foo() {
var a = 2;
console.log(a);
})
};
obj.a(); // 2
foo(); // ReferenceError: Not Defined
How is that I can access a function expression within obj, but not in the global object?
Edits: for cohesion and clarity
You're confusing a couple of different things here.
Your first statement is a function expression, not a function declaration:
(function foo() {
var a = 3;
console.log(a);
});
This happens to be a named function expression ("foo"), but it does not introduce a variable foo in this scope. If you wanted to introduce foo so that it can be called again, you need either a function declaration...
function foo() {
var a = 3;
console.log(a);
}
foo();
or, you need to assign the function expression to a variable:
var foo = function () {
var a = 3;
console.log(a);
}
foo();
Your next bit of code, the object declaration, effectively does this by assigning the function expression to a variable, obj.a:
var obj = {
a: (function foo() {
var a = 2;
console.log(a);
})
};
The error in your thinking here is due to confusion around foo. In both cases, foo is the name of the function, but it's not actually relevant to invoking the function. You should drop the foo because it's only confusing things.
In essence, your first snippet is equivalent to:
(function () { alert('x'); });
This line of code defines an anonymous function, but does nothing with it. The function exists briefly, is never invoked, and then is lost, because it is not assigned to anything.
Your second snippet is equivalent to:
var x = function () { alert('y') };
This code defines a variable, x, and assigns a function to it. The function can then be invoked with x(), and the function remains available as long as x is in scope.
Your original question is:
How can an object access function expression?
Which doesn't really make sense. The object can't "access the function expression", it just contains a property to which a function has been assigned, while the snippet outside the object did not retain the function in a way that would allow you to invoke it.
I have a self invoking function in javascript and I have another function in the same file where I need the value of a variable that is inside the self-invoking function. How can I do that?
Edit: So I can get one variable, but how about more variables or an array?
And I also have a semicolon at the beggining, how to deal with it:
;(function() {
...
})();
You need to set it as part of the return. Depending upon your exact pattern it could go like
var app =(function(){
var x = 5;
function app() {
}
app.x = x;
return app;
})();
Simple define the variable not in the function but before:
var a = 1;
(function(){ /* do stuff and use a*/})();
function(){
// use a again
}
var x = (function(y) { return y + 2; })(2);
alert(x);
Works just like this:
function addTwo(y) { return y + 2; }
x = addTwo(2);
//Your self invoking func
(function(){
var getStuff = holdsStuff();
console.log(getStuff.a); //getStuff.b, getStuff.cArr etc;
})();
//func in same file that holds the vars that you need.
function holdsStuff(){
var a = 10;
var b = 15;
var cArr = [1,2,3,4,5];
return { a: a, b: b, cArr: cArr};
}
I understand the general idea behind the this keyword but I'm having trouble figuring out what it actually refers to in practice. For example, in both these example exercises, I guessed the wrong number.
for question1, I said that the alert would be '5', because it is referring to the this.x outside the anonymous function in the function.
In question2, I thought the alert would be 5 because this line
var alertX = o.alertX;
would bind the value 5 for property x inside the variable o to the new variable 'alertX' which becomes the function call in the next line: alertX();
Can you explain why I'm wrong?
var question1 = function() {
this.x = 5;
(function() {
var x = 3;
this.x = x;
})();
alert(this.x);
};
var answer1 = 3;
var question2 = function() {
this.x = 9;
var o = {
'x':5,
'alertX':function() { alert(this.x); }
};
var alertX = o.alertX;
alertX();
}
var answer2 = 9;
In the first case, when you invoke a method with no explicit receiver this is the Global object (the window in a web browser).
Similarly in the second case: even though the function is defined on the object, and you are inside another, by invoking the function with alertx() the this is set to the Global/window.
In short:
For foo.bar(), the this inside of bar will be foo.
For bar(), the this will be the Global object.
This includes so-called "self-invoking lambdas", i.e. (function(){ ... })().
For bar.call(whee) and bar.apply(whee), the this will be whee (because that's what these methods do).
Another example:
var o1 = { name:"o1", f:function(){ console.log(this.name) } };
var o2 = { name:"o2" };
o2.gogogo = o1.f;
o2.gogogo(); // Will output "o2"
These are good examples of how interesting this becomes in Javascript. this always refers to the context in which it was invoked / called, not simply where it is at that moment! question2 is a perfect example of it.
I'm assuming you are invoking these globally like so:
question1();
question2();
In question1:
You have an anonymous function that is ran after you first set x to 5. This anonymous function if not set to a variable, inside a function etc, would have this set to the global variable of window. But you have it within a function & set to variable question1. So when it runs itself, it sets this's (which is question1 function) x variable to 3.
In question2:
X is originally set to 9, this being question2 in this instance. Now the part that is throwing you off is that, even though within the o {} object you set x : 5. And your alertX function is calling this.x. All of this would lead you to think it will alert 5! But you are invoking your alert function outside of the o {} object, hence the this refers to question2 function again!
Put the following into your browser's console
var x = -1, log = function(){ // set up some stuff
if(console) if(console.log) return console.log.apply(console, arguments),undefined;
return alert(arguments.join(', ')),undefined;
},
question1 = function() {
this.x = 5; // question1.x is 5
(function() { // anonymous function fires in global 'window'
var x = 3; // so window.x is now 3
this.x = x; // this is window
})();
log('ans1',this.x,this); // see below
},
question2 = function() {
this.x = 9; // question2.x is 9
var o = {
'x':5, // o.x is 5
'alertX':function() { log('ans2',this.x,this); }
};
var alertX = o.alertX; // alertX === o.alertX
alertX(); // being called in global scope
// to make alertX have scope of question2
this.alertX = o.alertX; // this is question2
this.alertX(); // so we're calling from question2
},
a1 = new question1(), // note the new operator
a2 = new question2();
undefined;
And you'll get
ans1 5 question1
ans2 3 Window
ans2 9 question2
var foo = function(){};
foo.prototype.value = 5;
foo.prototype.addValue = function(){ foo.value = 6; }
function bar(func)
{
func(); // I'm running the function!
}
bar(foo.addValue); // pass in the function
alert(foo.value); // it's now 6!
Why is the no alert prompt when running this JavaScript code?
The correct code should be
var foo = function(){};
foo.prototype.value = 5;
foo.prototype.addValue = function(){ foo.value = 6; }
function bar(func)
{
func(); // I'm running the function!
}
bar(foo.prototype.addValue); // pass in the function
alert(foo.value);
or
var foo = function(){};
foo.prototype.value = 5;
foo.prototype.addValue = function(){ foo.value = 6; }
function bar(func)
{
func(); // I'm running the function!
}
bar(new foo().addValue); // pass in the function
alert(foo.value);
Since you are declaring a prototype called addValue, foo itself does not contain addValue. To refer to that function, you have to use foo.prototype.addValue. Note that in this case, foo contains both foo.prototype.value with a value of 5, and foo.value with a value of 6.
Alternatively, if the intention is to create a new object, then the object will inherit the addValue function, so calling new foo().addValue works.
Well, refactoring your code would give:
var foo = {
value: 5,
addValue: function(){
foo.value = 6;
}
};
function bar(func){
func(); // I'm running the function!
}
bar(foo.addValue); // pass in the function
alert(foo.value); // it's now 6!
Setting foo.prototype.addValue won't help you to define foo.addValue.
And the reason for using foo.value instead of this.value is to resolve scope problems when calling via bar()