Suppose I have a JavaScript function. and it contain a variable x;
function A(){
var x = 12+34;
}
Is it possible to access x from outside function x?
No, the ability to do so would not make any sense. Suppose we changed your function slightly and called it 3 times:
function x(n){
var x = n+34;
}
x(1), x(2), x(3);
At this point, the function has run 3 times, so the variable x has been created 3 times — which x would you expect to be able to access? Then there's garbage collection; how could references and data be cleared from memory if the browser had to keep variables alive once they're no longer in scope?
If you want to, you can do something like this:
function x() {
x.x = 12+34;
}
x();
or, if the variable will be static/constant as you have it
function x() { }
x.x = 12+34;
or finally, as others have pointed out, by declaring x under a different name outside of the function's scope:
var y;
function x() {
y = 12+34;
}
x();
You can not access it directly by its name, try removing 'var' from the variable declaration, as this should make the variables globals, or placing them outside the ready function. and return the value of x from the function.
You can do some thing like this:
$(document).ready(function() {
var x;
function x(){
x = 12+34;
return x;
}
alert(x());
});
Here is its jsfiddle
Hope this helps.
Yes, but not as scoped in your example above. You must use closure. Consider the following:
var x,
A = function () {
x = 12 + 34;
};
In this manner you can access x from inside the function A. What is even better is that x has direct access to the private members of A and so can be used to leak private data outside of A.
Related
I spent a long time trying to complete this function only to see that the syntax i was trying was not being accepted.
The countSheep function in code academy tells you to complete the function and gives you a newNumber variable that seems to not be defined in the local scope. So I tried to give it the "var" keyword. For some reason I can't understand the var keyword was not necessary and in order to complete the function and get it to pass the test I had to use the following:
as opposed to defining the variable I just used
newNumber = number -1; // can also be written as newNumber -= 1;
passed newNumber to the function
OR
not defined the newNumber variable and just invoke the function using n-1 as the parameter.
Here is the code that code academy gave us to solve.
function countSheep(number) {
if (number === 0) {
console.log("Zzzzzz");// Put your base case here
} else {
console.log("Another sheep jumps over the fence.");
// Define the variable newNumber as
// 1 less than the input variable number
newNumber = number - 1;
// Recursively call the function
// with newNumber as the parameter
countSheep(newNumber);
}
}
Can someone please tell me why the var keyword is not necessary inside of the function to define the newNumber variable. I appreciate it.
if you declare newNumber using var it is only accessable on
the scope of
else block
.But if you don`t use var it will not be
local,means can be accessed on the outer scope**(countSheep).**
newNumber is a global variable that means, it is assigned to the global object. In browsers this is the window object:
function f(x) {
y = x;
}
console.log(window.y);
f(123);
console.log(window.y);
To create a local variable that is only accessible within the function, use var:
function f(x) {
var y = x;
console.log("within f:", y);
}
f(123);
console.log("outside f:", window.y);
To create a local variable that is only accessible within its surrounding block, use let or const:
function f(x) {
{
let y = x;
console.log("inside block", y);
}
try {y} catch (e) {console.log("outside block:", e.message)}
}
f(123);
From the MDN description of Function:
Note: Functions created with the Function constructor do not create
closures to their creation contexts; they always are created in the
global scope. When running them, they will only be able to access
their own local variables and global ones, not the ones from the scope
in which the Function constructor was called. This is different from
using eval with code for a function expression.
I understand,
var y = 10;
var tester;
function test(){
var x = 5;
tester = new Function("a", "b", "alert(y);");
tester(5, 10);
}
test(); // alerts 10
Replacing the tester = new Function("a", "b", "alert(y);"); with tester = new Function("a", "b", "alert(x);");, I will get
// ReferenceError: x is not defined
But couldn't understand the author's line-
...they always are created in the global scope.
I mean how is the new Function("a", "b", "alert(y);"); nested within the test fn is in global scope?
In fact, accessing it from outside the test fn will simply result in
Uncought TypeError:tester is not a function
Please elucidate.
In your example, "created in the global scope" means that tester will not have closure over x from test:
function test(){
var x = 5;
tester = new Function("a", "b", "alert(x);"); // this will not show x
tester(5, 10);
}
When you new up a Function, it does not automatically capture the current scope like declaring one would. If you were to simply declare and return a function, it will have closure:
function test(){
var x = 5;
tester = function (a, b) {
alert(x); // this will show x
};
tester(5, 10);
}
This is the trade-off you make for having dynamically compiled functions. You can have closure if you write the function in ahead of time or you can have a dynamic body but lose closure over the surrounding scope(s).
This caveat doesn't usually matter, but consider the (slightly contrived) case where you build a function body as a string, then pass it to a function constructor to actually be evaluated:
function addOne(x) {
return compile("return " + x + " + 1");
}
function addTwo(x) {
return compile("return " + x + " + 2");
}
function compile(str) {
return new Function(str);
}
Because the function is instantiated by compile, any closure would grab str rather than x. Since compile does not close over any other function, things get a bit weird and the function returned by compile will always hold a closure-reference to str (which could be awful for garbage collection).
Instead, to simplify all of this, the spec just makes a blanket rule that new Function does not have any closure.
You have to create an object to expose via return inside the test() function for it to be global. In other words, add var pub = {} and name your internal functions as properties and/or methods of pub (for example pub.tester = new func) then just before closing test() say return pub. So, that way it will be publically available (as test.tester). It's Called the Revealing Module Pattern.
What it means is that inside the function you can only refer to global variables, as you've found. However, the reference to the function itself is still in the local scope where it was created.
I'm confused as to where the confusion is.
It says that the function will be in global scope...and therefore will only have access to its own scope and the global scope, not variables local to the scope in which it was created.
You tested it and it has access to its own scope and the global scope, not variables local to the scope in which it was created.
So where's the confusion?
Is it in your assigning of the function to the variable testing? testing is just a local variable with a reference to the function...that has nothing to do with the scope of the creation of the function.
Scope is lexical, and has to do with where the function is created, not what random variables a function reference happens to be assigned to at runtime. And the documentation is telling you that when you make a function this way it acts as if it was created in the global scope...so it's acting completely as expected.
Here's an illustration:
This:
var y = 10;
var tester;
function test()
{
var x = 5;
// 10 and errors as not defined
tester = new Function("console.log(y); console.log(x);");
}
Is similar to this:
var y = 10;
var tester;
function test()
{
var x = 5;
// also 10 and errors as not defined
tester = something;
}
function something()
{
console.log(y);
console.log(x);
}
NOT
var y = 10;
var tester;
function test()
{
var x = 5;
// 10 and 5...since x is local to the function creation
tester = function()
{
console.log(y);
console.log(x);
}
}
From what i know, a function say A defined within another function say B has access to local variables of B as well.
function B() {
var x = 10;
function A() {
console.log(x); //will result in 10
var y = 5;
}
console.log(y); //ReferenceError: y is not defined
}
However in the below example y gets printed. I know there is no such thing as block scope in javascript for "if block" but shouldn a declaration atleast be invisible outside of "if" i mean shouldnt var y be limited to if block?
function B() {
var x = 10;
if(1) {
console.log(x); //will result in 10
var y = 5;
}
console.log(y); will result in 5
}
JavaScript isn't truly block scoped. An if or for loop does not have its own scope. All variable declarations in any given scope (that is: global scope, or a function) are hoisted, and this visible anywhere inside that scope.
ECMAScript6 (Harmony) will, in all likelihood, introduce block-scope to JS, through the use of the new let keyword see the wiki:
for (let i=0;i<12;++i)
{
console.log(i);//logs i
}
console.log(i);//reference error
There also seems to be some confusion as far as terminology is concerned here: a closure is not the same as a scope.
The snippet above is an example of block-scoped code. The variable i is created at the start of the loop, and simply ceases to exist once the loop finishes. It is GC'ed (Garbage Collected). i is no more, bereft of life it rests in peace. Closures are something different entirely: they rely on variables that are not GC'ed, but can't be accessed from outside code. They can only be accessed through the return value of the closure:
var someClosure = (function()
{//this function creates a scope
var x = 123;
return {
getX: function()
{
return x;
},
setX: function(val)
{
return x = val;
}
};
}());
console.log(x);//reference error
console.log(someClosure.getX());//returns 123, so "x" still exists
That being said:
You can mimic a block-scoped loop through the use of a closure, though. Functions are scoped, and a closure is a function or object that is returned by a function. That means that the return value of a function has access to the entire function's scope. See this answer for details.
Apply what is explained there, and work out why this loop is "pseudo-scoped":
var foo = [1,2,3,4,5,6],
largerThan3 = (function(arr)
{
var resultArr = [];
for (var i=0;i<arr.length;++i)
{
if (arr[i] > 3)
resultArr.push(arr[i]);
}
return resultArr;
}(foo));
console.log(i);//reference error...
nope.
as you said - if blocks does not have their own closures in JS - which means everything is part of the outer closure (in this case - y is a local variable in B's closure). so it will be completely visible in B's body
How can I get access to my y() function?
function x() {
function y() {
return 1;
}
}
Is it possible at all?
It is scoped to x, kind of like:
function x() {
var y;
}
So, yes, from within x, and no otherwise.
If you wanted it to be, you could create it as a property on x:
var x = (function () {
function x() {
…
}
function y() {
…
}
x.y = y;
return x;
})();
You mean access it from outside the function x?
That's not possible, the function y doesn't exist when x is not running. It's declared locally inside x so it's only accessible inside x.
To make it accessible outside x you need to expose a reference to it outside the function. If you expose a reference to it, it survives after the function ends. For example:
function x() {
function y() {
return 1;
}
return y;
}
// get the reference to y
var f = x();
// call y
f();
You can get access to your y function inside of the scope of the x function Only.
But you can get access to the y function if you return it from your x function or assign it to a global variable or to the variable that is in scope outside of your x function. This is also know is closure, your y function will keep the reference in memory to the scope it was created in if you pass it around.
function x() {
var anotherNum= 2;
function y() {
return 1 + anotherNum;
}
return y;
}
Now you can get the y function along with the scope it was created in. Notice that it will use anotherNum in the computation as it was created in the x function.
var yFunc = x();
console.log(yFunc()) // will print 3
One way is to return it out of the scope
function x() {
function y() {
return 1;
}
return {
y:y
};
}
Whenever you call x(), it returns an object with the function y as a member
var a = x();
a.y(); //this returns 1
This is similar to the revealing module pattern described here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures?redirectlocale=en-US&redirectslug=JavaScript%2FGuide%2FClosures
Also good to read up on closures:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures?redirectlocale=en-US&redirectslug=JavaScript%2FGuide%2FClosures
Using JavaScript, say I have a function X, and in that function an object called objectX is created. function X returns objectX. Later in the code function Z(somevar, anObject) receives objectX as one of it's parameters.
Now in function Z, is objectX and all its properties referred to as anObject inside function Z?
And what happens if function Z returns anObject? Will the rest of the code see the object as "objectX" or "anObject"?
function X() {
...
objectX = {};
...
return objectX;
}
X();
function Z(anything, anObject) {
...
return anObject
}
Z(something, objectX);
anObject and objectX both are referencing to the same space in memory, so, name it as you want, it's always the same object.
Good luck!
This is mostly a question of scope.
function X() {
// local objectX, only accessible through this name inside X()
var objectX = {};
objectX.foo = 'bar';
return objectX;
}
function Z(somevar, anObject) {
// anObject is passed in as a parameter
// it's only accessible through this name inside Z()
anObject.foo = somevar;
return anObject;
}
// get the 'objectX' from X() and store it in global variable a
var a = X();
// pass the received 'objectX' into Z()
// note that the variable names objectX and anObject cannot be accessed
// because they are local variables of the functions X() / Z()
var b = Z('baz', a);
// a is now the same as b, they both reference the same var
// a.foo and b.foo both are set to 'baz'
I believe an example is the best way to teach. Here is some code (click here to see it in JS Bin):
// Defines the variable to keep track of how many objects X() defines.
var num = 1;
// Instantiate another variable to see if it is changed by Z().
var anObject;
// Creates an object with a comment and a random number.
function X() {
// Create an object and give it a name.
var objectX = {comment : "Creation #" + num};
// Increase the value of num.
num++;
// Add another random number between 0 and 100 inclusively.
objectX.randNum = Math.round(Math.random() * 100);
// Return objectX.
return objectX;
}
// Modifies the second parameter by adding the value of the first parameter.
function Z(somevar, anObject) {
anObject.somevar = somevar;
return anObject;
}
var objectX = X(), objectY = X();
objectX2 = Z('coolness', objectX);
// Notice that objectX is still the result of calling X() the first time.
alert("objectX.comment = " + objectX.comment);
// Notice that objectX is not equal to objectY.
alert("objectX === objectY evaluates to " + (objectX === objectY));
// Notice that objectX2 is the same thing as objectX.
alert("objectX === objectX2 evaulates to " + (objectX === objectX2));
// Notice that anObject is not defined.
alert("typeof anObject evaluates to " + (typeof anObject) + " after Z is called.");
alert("Now review the JavaScript code.");
If read through the comments, you will find the answers to your questions. First you will notice that in function Z, since I passed objectX as the second parameter, inside of the function, it could be referred to by anObject. Second you will notice that once outside of function Z, anObject no longer refers to objectX. The comments also reveal other things that are true in JavaScript.
Javascript has function scope. This means that every variable declared within a function, will only be accessible from within that function.
If you’d properly declared the objectX variable with var, as follows:
function X() {
...
var objectX = {};
...
return objectX;
}
then objectX would only be known as objectX inside the X function. Elsewhere, it would be known as whatever variable you’d assigned it to. Since in your code, you don’t assign the result of X() to anything, objectX would not be accessible from anywhere.
However, here’s one of Javascript’s more serious design flaws: if you don’t explicitly declare a variable (using the var statement, or as a function parameter), that variable will automatically become a global variable. That means that it will be accessible anywhere.
Because of this, in your code above, you can access objectX everywhere by that name.
anObject, on the other hand, is properly declared (as a parameter), and that means its scope will be limited to the Z function.
In short, the way your code is written, objectX is accessible everywhere by way of the objectX variable, and inside the function Z, you can reference it both as objectX and as anObject.
Do note, however, that global variables are a Bad Thing™, since they can make it quite hard to figure out what variable gets assigned by who, when, and why — as you’ve noticed.
While Javascript makes it impossible to completely avoid them, as a rule you should try to keep the scope of your variables as small as possible (scope = where in your program that variable can be accessed).
To that end, I would recommend refactoring your code like igorw has.
Here is link to jsfiddle
Lets take the following example below:
Person = function(name){
this.name = name;
}
function x(){
var john = new Person('john');
return john;
}
function z(tempVar, anObject){
var newObj = anObject;
newObj.name = tempVar;
return newObj;
}
myPerson = x();
console.log(myPerson.name); //john
console.log(z('peter', myPerson).name); //peter
console.log(myPerson.name); //peter
You can see, even though you created a new object in z but because they are referencing to the same object myPerson's name property is also changed after z() is called.