I've tried this:
function a_function(){
var data = "information";
});
console.log(data);
You can't. You need to create a variable outside of that scope and assign to it:
var data;
function a_function(){
data = "information";
});
a_function();
console.log(data);
Another answer has been posted mentioning learning about scope. Follow that advice and try to get your head around it early, it will save you a lot of hassle in the future.
Technically you can, though it's generally not a good idea:
function a_function() {
data = "information";
}
a_function();
console.log(data);
The reason this works is because, by not using the var keyword to declare a variable, JavaScript (being the good little dynamic language that it is) is writing to the data property of the "current" object, which is window. And, thus, globally accessible. It's basically the equivalent of doing this:
function a_function() {
window['data'] = "information";
}
a_function();
console.log(window['data']);
As I said, it's generally not a good idea. Other approaches include returning the value:
function a_function() {
var data = "information";
return data;
}
var data = a_function();
console.log(data);
Or perhaps creating the value in the larger scope and setting it in the function:
var data;
function a_function() {
data = "information";
}
a_function();
console.log(data);
Basically, in general you want to maintain scope and control flow and try to avoid "globals" where possible.
you need to read about scope and how it work .
http://www.w3schools.com/js/js_scope.asp
https://en.wikipedia.org/wiki/Scope_%28computer_science%29#JavaScript
For example a variable declared in a function exist only in this function. Once you are outside this fonction, the variable are deleted so it is undefined
You either have to pass the value to a variable in the scope that is shared by the console.log() call like:
var data;
function a_function(){
//note the ommission of the 'var' keyword
data = "information";
});
a_function();
console.log(data);
or you have to have the function return the value and use that as input to the log() method:
function a_function(){
var data = "information";
return data;
}
console.log(a_function());
or wrap the console.log() call in a helper function that your function calls from within its scope, passing data as an argument:
function log(data){
console.log(data);
}
function a_function(){
var data = "information";
log(data);
}
EDIT: as others have mentioned, while we can tell you all the ways to do this, it is better to learn more about scope and understand why the methods people suggest work.
If you want to ecapsulate data but use it outside of the function a_function, you need to return data and call a_function. Something like this should work:
function a_function() {
var data = "information";
return data;
};
var data = a_function();
Note, due to scope, data inside the function is different than data outside the function. If you don't create a new var named data outside the function, you will not be able to access data because it doesn't exist in the outer scope.
The following code demonstrates scope:
function a_function() {
var data = "information";
return data;
};
var data = "different information";
var data2 = a_function();
console.log(data);
console.log(data2);
The output from the code will yield:
different information
information
Related
I have a function as:
function Main(){
var self = this;
self.reserve=false;
self.change = function(){
self.reserve=!self.reserve
}
self.service={
to_add: 0, to_delete: 0,
init: function(data){
self.service.to_add = data[0];
self.service.to_delete = data[1];
},
custom_func: function(data){
self.service.init(data);
self.service.change;
},
/*there are many other functions here*/
}
}
Now as you can see inside the service object I need to reference everything like self.service.xxx.
But is there a better approach where I could reference the objects local variables directly like to_add=data[0] instead of self.service.add_to=data[0], but to use variables from other objects can follow the default way self.object.xxxx.
Reason: To reduce the script size. There are many such variables and functions inside the service object.
Note: Please change the question accordingly. I was not able to come up with any.
$(function(){
var astronautsData;
$.getJSON('http://api.open-notify.org/astros.json', doSomething);
function doSomething(data) {
astronautsData = data;
}
alert(astronautsData.people[0].name)
});
I would like to be able to use the data in every function I make, that's why I tried to put it in the variable astronautsData, but unfortunately astronautsdata is undefined.
You can access astronautsData inside doSomething.your alert() will get executed
before getJSON. that's why you are getting undefined.
$(function(){
var astronautsData;
$.getJSON('http://api.open-notify.org/astros.json', doSomething);
function doSomething(data) {
astronautsData = data;
alert(astronautsData.people[0].name)
}
});
Here you must understand one thing that getJSON is 'async'. Your alert method trying to show the data which gonna come in future. In order to solve this problem, you must use 'then', 'done' or 'fail' like below.
$(function(){
var astronautsData;
//Assign your getjson request
var jsonRequest = $.getJSON('http://api.open-notify.org/astros.json');
//This function runs once the getJSON method is success
jsonRequest.done(function(data){
astronautsData = data;
});
//This function runs after the success of getJSON
jsonRequest.then(function(){
//Here you have to do your alert ( This alert will give data )
alert(astronautsData);
});
//This alert will give undefined value as this line of code and getjson request runs parallelly
alert(astronautsData);
});
Your .getJSON is asynchronous.
Try using a Promise to wait for your call to be done :
prom = new Promise((resolve, reject) => {
$.getJSON('http://api.open-notify.org/astros.json', function(){
astronautsData = data;
resolve('Ajax done');
});
});
prom.then((successMessage) => {
console.log(successMessage);
alert(astronautsData.people[0].name)
});
Exposing variables in window/global scope is bad in my opinion. You should wrap it in a function (like a class of sorts) and expose it like this:
function Values(type) {
this.value1 = "something";
}
From this point you can use prototype to define additional functions on "Values" like so:
Values.prototype.doStuff = function() {
return this.value1 + ' addsomething';
};
Inside of the prototype function you can define/return promises or do whatever you want including assigning values to the instance. You can also assign the instance to a global variable to make it a singleton of sorts. Granted your still using a global variable for that but its the instance of Values assigned to the variable not the actual values that are stored.
This is a bit of an over simplification perhaps, but in a way this is how the global variables for lodash or jquery work, although they have a LOT more going on to check for existing global variables and such before attempting to define it on global scope as typically you want to avoid that.
you can use var at global scope (outside of all functions) to declare a global variable:
<script>
var astronautsData;
$(function(){
$.getJSON('http://api.open-notify.org/astros.json', doSomething);
function doSomething(data) {
astronautsData = data;
}
alert(astronautsData.people[0].name)
});
</script>
use global.astronautsData if you want it to be global
In the following code, I'm trying to get mydata passed to the callback. This is a sample problem from a bigger problem I'm having. I'm assuming this is a scope issue. What is wrong with my code and/or what should I do?
var EventEmitter = require('events').EventEmitter;
var myevent = new EventEmitter();
var mydata = 'my data!';
function myfunc (data, mydata) {
console.log(data);
console.log(mydata);
};
myevent.on('data', function(data, mydata) {myfunc(data,mydata)});
myevent.emit('data', "data!");
returns:
data!
undefined
I'd like it to return:
data!
my data!
The parameter mydata in the callback's parameter list is hiding the global variable of the same name.
As you passed no parameter in that position, its value is undefined.
Either:
change the name of the parameter, or
remove the parameter, or
pass the required value, e.g. myevent.emit('data', "data!", mydata);
p.s:
myevent.on('data', function(data, mydata) {myfunc(data,mydata)});
would be better just written as:
myevent.on('data', myfunc);
i'm going to make a wild guess (since i am not familiar with EventEmitter) and say that emit's first parameter is the name of the event, and the remaining parameters are passed to the handler.
if that is the case, you're not passing anything to the second callback parameter, which is why it comes in as undefined. try this instead:
myevent.emit('data', "data!", "mydata!");
note: i am ignoring your shadowing issue as it is not related to the problem, just a bad practice.
Modified code: You can access a global variable. from anywhere you do not need to pass it as parameter. even you pass a parameter. you can access a global variable using window.mydata since you are using nodejs you can access a global variable using global.mydata
var EventEmitter = require('events').EventEmitter;
var myevent = new EventEmitter();
var mydata = 'my data!';
function myfunc (data) {
console.log(data);
console.log(mydata);
};
myevent.on('data', myfunc);
myevent.emit('data', "data!");
Say I have some context where variables are set and a λ-function is called which uses them directly:
function outerContext(){
...
var data = ...; // some data the script uses
...
someObject.method = function(){
data; // the variable is used here
};
...
}
I know that the dynamically created function has a snapshot of the context it was created in, so data variable is accessible there.
What are the dangers I may face with such an approach when I use this dynamically created method? Should I always give this data as an argument or is it ok?
The inner function does not have access to a "snapshot", it has full access to the data variable.
function outer() {
var data = 1;
...
someObject.method = function () {
data = 42;
};
someObject.method();
// data == 42
}
(The real explanation being that when using data in the inner function, Javascript will try to figure out which scope data is in. It will traverse up the scope chain to find the place where the variable was created, and that's the variable that will be used.)
There's no "danger", this is one of the core competencies of Javascript. It's like an object method modifying an object's properties. Of course you need to take care what you want to do, do you really want to modify the variable or do you just want to use it locally?
For the "snapshot", you need to use a closure:
function outer() {
var data = 1;
...
someObject.method = (function (data) {
return function () {
data = 42;
}
})(data);
someObject.method();
// data == 1
}
I can't really think of any "dangers" besides the possibility of causing a circular reference and thus a memory leak in case of DOM objects or such.
It works much like a private variable in a class.
I am having some trouble with the classic javascript local variable scope topic, but dealing with a JSON variable. I have looked at other questions here regarding the same thing, but nothing has matched my case exactly, so here goes. I have a class that I have made from javascript that has 3 methods: func1, func2, and func3. I also have a local JSON variable that is being set in one of the methods from an ajax call I am making with jquery, but is not set when I call a method that returns that local variables value. I know the ajax is working fine, b/c I can display the data that is being returned and being set to the json variable fine with no problem. It is only happening when I call another method that interacts with that JSON variable. Here is a basic version of my code:
function func1(){
func2();
}
function func2(){
$.getJSON("http://webservice.mydomain.com/methodname&jsoncallback=?",
function(data){
this.z = eval("(" + data.d + ")");
alert(data.d); //this displays the data!
alert(this.z.ArrayProperty[0].Property1); //this displays
//the correct data too!
}
);
}
function func3(){
return this.z.ArrayProperty[0].Property1;
}
function myClass(var1, var2){
this.x = var1;
this.y = var2;
this.z = "";
this.func1 = func1;
this.func2 = func2;
this.func3 = func3;
}
And then in my .html page, I am having the following code:
var obj = new myClass(1,2);
obj.func1("abc");
alert(obj.func3()); //ERROR: this.z.ArrayProperty is undefined
Any ideas?!?! I am racking my mind!
Thanks
I don't think this is anything to do with scope.
Remember that the AJAX call is asynchronous so func3 is being called before the JSON has been returned and your anonymous function has had a chance to set this.z to anything.
I don't think "this" inside your callback is the same "this" that defined func2. Using the Prototype JavaScript library, you can use bind() to get around this.
You may be able to just add a new variable in func2, or use a bind function in whatever library you are using.
func2() {
var me = this;
$.getJSON("http://webservice.mydomain.com/methodname&jsoncallback=?",
function(data){
me.z = eval("(" + data.d + ")");
success = true;
alert(data.d); //this displays the data!
alert(this.z.ArrayProperty[0].Property1);
}
);
}
I could be completely wrong, but it look like the "this" variable is messing you up. "this" variable depends on how you call the function. It looks like you really don't want to be using that. Instead, I use:
func2() {
var that = this;
Then later in the code use:
function(data){
that.z = eval...