I think the question title sums it up pretty well, if not, let me explain:
I have a class, that one has a function and inside that function A I NEED to have another function (function B), which needs to access a variable of function A. I hope this is enough, I really can not find any better words of how to describe this issue.
I think you need arrow functions for that
class Some() {
constructor() {
/* ... */
}
A(params) {
let localVariable = 1
const B = () => {
// here you can access to the context (this)
// and to A local variables (params, localVariable )
}
}
}
If i understood you correctly. And please ask more specific questions next time. Also try to share your code. It would be easier to understand
This sounds like a design problem. It sounds like you're attempting to break variable scoping rules. It seems to me, that this is what you're trying to do:
class some_class {
A_function() {
let variable1 = 5;
}
B_function() {
let variable1 = 10;
}
}
'variable1' is defined in A_function and is not accessible to B_function because of scoping rules. In fact, the variable1 in A_function and the variable1 in B_function are different variables.
However, a better implementation, that would likely work as you intend would be more like this:
class some_class {
constructor() {
this.variable1 = 5;
}
A_function() {
this.variable1 = 10;
}
B_function() {
this.variable1 = 15;
}
}
Now, this.variable1 is defined as a property of the class and is accessible to both functions. Either function can modify the value of the variable.
Is this what you have in mind?
Related
I have a function in the prototype of the constructor:
function Animal(name) {
this.name = name
}
Animal.prototype.generateToys = function(numberOfToys) {
if(numberOfToys == 1) {
this.createToys();
}
else {
this.createToys();
}
}
The createToys still needs to be declared. And that´s where my question is pointing towards. Assuming that generateToys will be the only method that will call createToys(), would it be better to create createToys inside the method generateToys like so:
function Animal(name) {
this.name = name
}
Animal.prototype.generateToys = function(numberOfToys) {
if(numberOfToys == 1) {
this.createToys();
}
else {
this.createToys();
}
function createToys() {
...
...
...
}
}
Or would you create it as a method(prototype) like the following:
Animal.prototype.createToys = function() {
...
...
...
}
What would be better and why? :)
If you put it inside the generateToys() method, it will be re-declared every single time you call that method, and then be removed from scope when the method completes. Most of the time this isn't what you want, so you'd prefer to create it as a separate method.
That depends on your architecture.
If you plan to have many instances of Animal then adding your method to the prototype is better, otherwise you will be creating a lot of private functions and that is costly (in terms of performance).
declaring the function inside the prototype limits the visibility outside that scope and cause the function to be declared everytime you call Animal.prototype.generateToys() (waste of memory)
Animal.prototype.generateToys = function(numberOfToys) {
var createToys = function createToys() {
}
})
declaring it on the prototype means that each of your instance can call it directly and you will have only one spot in memory with that declaration because the prototype itself it's a single reference shared by all your instances.
I'm trying to reuse a complicated function, and it would work perfectly if I could change the value of a local variable that's inside a conditional inside that function.
To boil it down:
var func = complicated_function() {
// lots of code
if (something) {
var localvar = 35;
}
// lots of code
}
I need localvar to be some other number.
Is there any way to assign localvar to something else, without actually modify anything in the function itself?
Update: The answer is yes! See my response below.
Is there any way to assign localvar to something else, without actually modify anything in the function itself?
Nope.
No, but it is possible to assign it conditionally so that the function signature (basically, the required input and output) does not change. Add a parameter and have it default to its current value:
var func = complicated_function(myLocalVar) {
// lots of code
if (something) {
// if myLocalVar has not been set, use 35.
// if it has been set, use that value
var localvar = (myLocalVar === undefined)?35:myLocalVar;
}
// lots of code
}
No.
Without changing the complicated function there is no way, in javascript you can manipilate this by using call and apply. You can override functions in the complicated function or add new if this is an option (but they won't be able to access the local variable localvar).
this is more for fun my real answer is still no.
If you are feeling crazy :)
var complicatedFunction = function() {
var i = 10;
var internalStuff = function() {
console.log(i); // 10 or 12?
};
return internalStuff();
};
var complicatedFunction;
eval("complicatedFunction = " + complicatedFunction.toString().replace(/i = 10/, 'i = 12'));
complicatedFunction(); //# => 12
If the function uses this.localvar:
var func = function() {
alert(this.localvar)
if (true) {
var localvar = 35;
}
// lots of code
alert(this.localvar)
}
var obj = {localvar: 10};
func.call(obj); // alerts 10 twice
If not, then you can't change it without changing the function.
In javascript variables are "pushed" to the top of their function. Variables in javascript have function scope, not "curly brace" scope like C, C++, Java, and C#.
This is the same code with you (the developer) manually pushing it to the top:
var func = complicated_function() {
var localvar = 0;
// lots of code
if (something) {
localvar = 35;
}
// lots of code
}
Does declaring the variable "up" one function help you out? At least the declaration is isolated.
function whatever() {
var localvar = 0;
var func = function() {
var something = true;
// lots of code
if (something) {
localvar = 35;
}
// lots of code
};
func();
alert(localvar);
}
whatever();
Here is the jsFiddle: http://jsfiddle.net/Gjjqx/
See Crockford:
http://javascript.crockford.com/code.html
JavaScript does not have block scope, so defining variables in blocks can confuse programmers who are experienced with other C family languages. Define all variables at the top of the function.
I asked this question about three weeks ago and within a half hour got five answers that all basically told me it wasn't possible.
But I'm pleased to announce that the answer is YES, it can be done!
Here's how:
var newfunc = func.toString().replace('35', '42');
eval('newfunc = ' + newfunc);
newfunc();
Of course, it uses eval, which probably means that it's evil, or at least very inadvisable, but in this particular case, it works.
I'm using class members to hold constants. E.g.:
function Foo() {
}
Foo.CONSTANT1 = 1;
Foo.CONSTANT2 = 2;
This works fine, except that it seems a bit unorganized, with all the code that is specific to Foo laying around in global scope. So I thought about moving the constant declaration to inside the Foo() declaration, but then wouldn't that code execute everytime Foo is constructed?
I'm coming from Java where everything is enclosed in a class body, so I'm thinking JavaScript might have something similar to that or some work around that mimics it.
All you're doing in your code is adding a property named CONSTANT with the value 1 to the Function object named Foo, then overwriting it immediately with the value 2.
I'm not too familiar with other languages, but I don't believe javascript is able to do what you seem to be attempting.
None of the properties you're adding to Foo will ever execute. They're just stored in that namespace.
Maybe you wanted to prototype some property onto Foo?
function Foo() {
}
Foo.prototype.CONSTANT1 = 1;
Foo.prototype.CONSTANT2 = 2;
Not quite what you're after though.
You must make your constants like you said :
function Foo() {
}
Foo.CONSTANT1 = 1;
Foo.CONSTANT2 = 2;
And you access like that :
Foo.CONSTANT1;
or
anInstanceOfFoo.__proto__.constructor.CONSTANT1;
All other solutions alloc an other part of memory when you create an other object, so it's not a constant. You should not do that :
Foo.prototype.CONSTANT1 = 1;
IF the constants are to be used inside of the object only:
function Foo() {
var CONSTANT1 = 1,CONSTANT2 = 2;
}
If not, do it like this:
function Foo(){
this.CONSTANT1=1;
this.CONSTANT2=2;
}
It's much more readable and easier to work out what the function does.
If you're using jQuery, you can use $.extend function to categorize everything.
var MyClass = $.extend(function() {
$.extend(this, {
parameter: 'param',
func: function() {
console.log(this.parameter);
}
});
// some code to do at construction time
}, {
CONST: 'const'
}
);
var a = new MyClass();
var b = new MyClass();
b.parameter = MyClass.CONST;
a.func(); // console: param
b.func(); // console: const
First, I recommend moving your class declaration inside of an IIFE. This cleans up the code, making it more self-contained, and allows you to use local variables without polluting the global namespace. Your code becomes:
var Foo = (function() {
function Foo() {
}
Foo.CONSTANT1 = 1;
Foo.CONSTANT2 = 2;
return Foo;
})();
The problem with assigning constants directly to the class as attributes is that those are writable. See this snippet:
var output = document.getElementById("output");
var Foo = (function() {
function Foo() {
}
Foo.CONSTANT1 = 1;
Foo.CONSTANT2 = 2;
return Foo;
})();
Foo.CONSTANT1 = "I'm not very constant";
output.innerHTML = Foo.CONSTANT1;
<div id="output"></div>
The best solution I have found is to define read-only properties for accessing the constants outside of the class.
var output = document.getElementById("output");
var Foo = (function() {
const CONSTANT1 = "I'm very constant";
function Foo() {
}
Object.defineProperty(Foo, "CONSTANT1", {
get: function() {
return CONSTANT1;
},
});
return Foo;
})();
Foo.CONSTANT1 = "some other value";
output.innerHTML = Foo.CONSTANT1;
<div id="output"></div>
(Technically you could ditch the const CONSTANT1 statement and just return the value from the property definition, but I prefer this because it makes it easier to see all the constants at a glance.)
what you are doing is fine (assuming you realize that your example is just setting the same property twice); it is the equivalent of a static variable in Java (as close as you can get, at least without doing a lot of work). Also, its not entirely global, since its on the constructor function, it is effectively namespaced to your 'class'.
Your constants are just variables, and you won't know if you try and inadvertently overwrite them. Also note that Javascript lacks the notion of "class".
I'd suggest you create functions that return values that you need constant.
To get the taste of Javascript, find Javascript: the Good Parts and learn the idiomatic ways. Javascript is very different from Java.
Also with namespaces
var Constants = {
Const1: function () {
Const1.prototype.CONSTANT1 = 1;
Const1.prototype.CONSTANT2 = 2;
},
Const2: function () {
Const2.prototype.CONSTANT3 = 4;
Const2.prototype.CONSTANT4 = 3;
}
};
You said your coming from Java - why don't you store that class in 1 file then and constants at the end of the file. This is what I use:
filename: PopupWindow.js
function PopupWindow() {
//private class memebers
var popup, lightbox;
//public class memeber or method (it is the same in JS if I am right)
this.myfuncOrmyMemeber = function() {};
}
//static variable
PopupWindow._instance = null;
//same thing again with constant-like name (you can't have "final" in JS if I am right, so it is not immutable constant but its close enough ;) - just remember not to set varibales with BIG_LETTERS :D)
PopupWindow.MY_CONSTANT = 1;
//yea, and same thing with static methods again
PopupWindow._getInstance = function() {};
So only difference is the position of static stuff. It is not nicly aligned inside class curly braces, but who cares, its always ctrl+click in IDE (or I use ctr+l to show all class methods - IntellijIdea can do that in JS dunno how about other IDEs) so your not gonna search it by your eye ;)
Yea and I use _ before static method - it is not needed, I don't know why I started to do that :)
I'm working with several functions which need to pass a variable back and forth. Should I use a global variable or another method instead? I would also appreciate an example or two on how to implement it.
Thanks, Elliot Bonneville
Psuedocode of my functions:
function GetXML() {//this would be a function which reads in an XML file.
//Preferably it would also generate or set an object to hold the XML data.
}
function UseXMLData() { //I would use the XML data here.
}
function UseXMLDataHereAsWell() { //And here as well.
}
Global variables are, as you probably guessed, considered bad. Any other code on the page can modify them - often because another programmer accidentally picks the same name. You can try to mitigate this effect by choosing really strange names, but then you get a bunch of really strange names.
There are a lot of ways to minimize the number of global variables you create in JavaScript. One way is to store all your variables under a single object - that's what jQuery does (Technically jQuery uses two - $ and jQuery.)
If you know what you're doing, you often don't have to create any global variables - just wrap all your code in a function that you invoke immediately.
Bad example - pollutes the global namespace unnecessarily:
var appleCount = 0;
function addApple() {
appleCount = appleCount + 1;
}
function howManyApples() {
return appleCount;
}
addApple();
alert(howManyApples());
Better example - only creates one global variable:
var appleCounter = {
count: 0,
add: function() {
this.count = this.count + 1;
},
howMany: function() {
return this.count;
}
};
appleCounter.add();
alert(appleCounter.howMany());
Best example - creates no global variables:
(function(){
var appleCounter = {
count: 0,
add: function() {
this.count = this.count + 1;
},
howMany: function() {
return this.count;
}
};
appleCounter.add();
alert(appleCounter.howMany());
})();
The best solution for what you're trying to do would be to wrap all your data into an object and make your functions be methods on the object:
function MyXMLClass() {
this.data = null;
}
MyXMLClass.prototype = {
GetXML: function() {
this.data = ...;
},
UseXMLData: function() {
// use this.data
},
/* etc. */
};
And then you can just use it like this:
var x = new MyXMLClass();
x.GetXML();
x.UseXMLData();
...
Global variables should be avoided in reusable scripts.
If you're writing simple functions that will only be used in one page, there's nothing wrong with using globals.
If you're writing a reusable component or a complex web page, you should use closures or namespaces instead.
For more specific advice, please provide more detail.
EDIT:
You should create an XmlData class.
For example:
function XmlData(...) {
this.data = ...;
}
XmlData.prototype.doSomething = function(...) {
//Use this.data
}
Depending on how what your data comes from, you may want to make a separate function to retrieve the data.
Here is a good explanation.
Create a namespace, put all your functions within that namespace.
MyNS = {
x: 1, y: 2 // Here you define shared variables
};
MyNS.func1 = function(){}; // Here you define your functions that need those variables
Avoid global variables, it's bad programming. Try pass it as an argument or use name spacing to restrict its scope.
Is there any way to change a variable while out of scope? I know in general, you cannot, but I'm wondering if there are any tricks or overrides. For example, is there any way to make the following work:
function blah(){
var a = 1
}
a = 2;
alert(blah());
EDIT (for clarification):
The hypothetical scenario would be modifying a variable that is used in a setInterval function which is also out of scope and in an un-editable previous javascript file. It's a pretty wacky scenario, but it's the one I intend to ask about.
No. No tricks or overrides. You have to plan to have both places be able to see the variable in the same scope.
The only trick I can think of regarding scope is using window in a browser to get to the global object. This can help you get to a "hidden" variable--one that's in scope but whose name has been overtaken by a local variable (or other variable closer in the scope chain).
Closures and classes can afford you some other tricks with scope, but none that allow you to override the scoping rules entirely.
i don't see why you would need to do that, if you need a variable that is accessible from the outside, just declare it on the outside.
now, if you are asking this just because you are trying to learn something, good for you.
var a = 0;
function blah() {
a = 1;
return a;
}
a = 2;
alert(blah());
You can return the value from the function, of course:
function blah() {
var a=1;
return a;
}
But I assume that's not quite what you had in mind. Because a function invocation creates a closure over local variables, it's not generally possible to modify the values once the closure is created.
Objects are somewhat different, because they're reference values.
function blah1(v) {
setInterval(function() {
console.log("blah1 "+v);
}, 500);
}
function blah2(v) {
setInterval(function() {
console.log("blah2 "+v.a);
}, 500);
}
var a = 1;
var b = {a: 1};
blah1(a);
blah2(b);
setInterval(function() {
a++;
}, 2000);
setInterval(function() {
b.a++;
}, 2000);
If you run this in an environment with a console object, you'll see that the value reported in blah2 changes after 2 seconds, but blah1 just goes on using the same value for v.
Functions can access variables declared outside their scope, if they are declared before the function itself:
var a = 0;
function blah() {
a = 1;
}
a = 2;
alert(blah());
Note that your use of var a inside the function declared a local variable named a; here, we omit the keyword as otherwise it would hide a as declared in the outer scope!
No, that will never work, but you could use a global:
var a;
function blah(){
a = 1
}
a = 2;
alert(blah());
or use a closure:
function bleh() {
var a;
function blah(){
a = 1
}
a = 2;
alert(blah());
}
or you could pass it around with a return (which behaves differently, but probably is what you want to do):
function blah(a){
a = 1
return a;
}
a = 2;
alert(blah(a));