I have a variable myVariable which is continuously changing. At some point I want to capture the value of myVariable (not a reference to myVariable) into another variable myVariableAtSomePoint.
Example code:
var myVariable = 1;
function test () {
var myVariableAtSomePoint= myVariable;
console.log(myVariableAtSomePoint);
}
myVariable = 2;
test(); // Prints 2, instead of 1.
You mention in your comments that myVariable is a number. Since myVariable houses a primitive type, simply use the code below:
myVariableAtSomePoint = myVariable;
Take a look at JAVASCRIPT: PASSING BY VALUE OR BY REFERENCE. Here's a quote:
When passing in a primitive type variable like a string or a number,
the value is passed in by value.
I would also suggest reading: How do I correctly clone a JavaScript object?
EDIT:
I believe that you're assuming that the placement of the function in the code affects the value of the variables. It does not. See examples below:
This:
function test () {
var myVariableAtSomePoint= myVariable;
console.log(myVariableAtSomePoint);
}
myVariable = 2;
test(); // Prints 2, instead of 1.
Is the same as this:
var myVariable = 1;
function test () {
var myVariableAtSomePoint= myVariable;
console.log(myVariableAtSomePoint);
}
myVariable = 2;
test(); // Prints 2, instead of 1.
Your problem is that you're changing the value of myVariable before you're assigning it to myVariableAtSomePoint. For this to work as you want, you'll need to call the test() function before you change the value of myVariable
var myVariable = 1;
function test () {
var myVariableAtSomePoint= myVariable;
console.log(myVariableAtSomePoint);
}
test(); // Prints 1
myVariable = 2;
test(); // Prints 2
IMPORTANT: No matter the placement of the function, the code inside test() is not executed until you call the function.
The variable only holds the reference and nothing else. If you want a copy of the object that the variable is pointing to, you will need some way to copy that object.
Either you can implement a copy method on the object itself (if you know what properties it has) or you can iterate through all properties on the object using a for ... in loop and copy them to a newly allocated object.
Something like:
//o is the object you want to copy
var o2 = {}; //gives a new object
for (x in o) {
o2[x] = o[x];
}
Your code:
var myVariable = 1;
function test () {
var myVariableAtSomePoint= myVariable;
console.log(myVariableAtSomePoint);
}
myVariable = 2;
test(); // Prints 2, instead of 1.
You assign 2 to myVariable, and then assign myVariable (which has now value of 2) to myVariableAtSomePoint via test() so of course it is 2. You don't need any magic copying here (since numbers are primitive) just assigment is enough.
You'll just need to copy each property on the object, of course if there are sub-objects they might get passed by reference as well:
function copy(o) { //could be called "clone"
var i, n;
n = {};
for (i in o)
{
if (o.hasOwnProperty(i)) {
n[i] = o[i];
}
}
return n;
}
You can do something this to do exactly what you wanted. It is slightly more involved however.
var myVariable = 1;
var test = null;
(function() {
const myVariableAtSomePoint = myVariable;
test = function() {
console.log(myVariableAtSomePoint);
}
})();
myVariable = 2;
test(); // Prints 1
Related
I have a function that returns a variable and a function which edit the variable value.
But it's not working and I don't know why.
And what is the correct way to do this?
Here is my code:
function t(){
var test = 1;
var changeTest = function(){
test++;
}
return {
changeTest:changeTest,
test:test
}
}
var b = t();
b.changeTest();
console.log(b.test) // the value is 1 not 2
The value of test is a primitive and so it is indeed not a reference.
A solution: make the exposed test property a getter, so that the value of the private test variable is retrieved at the moment the property is accessed:
return {
changeTest:changeTest,
get test() { return test }
}
function t(){
var test = 1;
var changeTest = function(){
test++;
}
return {
changeTest,
get test() { return test }
}
}
var b = t();
b.changeTest();
console.log(b.test);
With this pattern, the test variable remains private, and you only expose the features you want to. So in this case you allow explicitly to read the test value, but not to write it.
NB: you can shorten the object literal notation to just:
return {
changeTest,
get test() { return test }
}
In changeTest you have to use this.test instead of test.
function t(){
var test = 1;
var changeTest = function(){
this.test++;
}
return {
changeTest:changeTest,
test:test
}
}
var b = t();
b.changeTest();
console.log(b.test) // the value is 1 not 2
If you would like to increase inside of the function, you need to use this keyword inside, just like the following:
function t(){
const changeTest = function() { this.test++; };
return { changeTest, test: 1 };
}
const b = t();
console.log('original value', b.test);
b.changeTest();
console.log('increased value', b.test);
The reason is why it is happening because you are not modifying the value inside, it is called lexical closure what you face with, as the documentations states:
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.
Using the this keyword the code accesses the proper test variable.
For further explanation please read further here:
Closures: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
I hope this helps!
I am trying to understand closures.
var a = 1;
var g = function () {
var a = a;
return function() {
console.log(a);
}
}
g()();
As far as I know, the function invocation g()() should log the value of a, i.e. 1. But it is logging undefined on the console. I know my concept is weak somewhere, but am not able to figure out even after spending few hours. Can someone help?
JavaScript hoists var declaration in the entire function scope. The variable from the outer scope var a = 1 is overwritten.
The example is equivalent to this:
var a = 1;
var g = function () {
var a; // a is undefined
a = a; // a = undefined
return function() {
console.log(a);
}
}
g()();
Without initial value assignment, a is simply undefined. Later you assign the variable to itself a = a, which is a noop and a remains undefined.
For more information about variables hoisting, check this article.
The problem is the line
var a = a;
This is both declaring a locally scoped variable and assigning it to itself - it's not interacting with the global a. You need to use a differently named local variable:
var a = 1;
var g = function() {
var b = a;
return function() {
console.log(b);
}
}
g()();
I have the following code in JSfiddle.
var a = 1;
function five() {
this.a = 5;
console.log(a); //JSfiddle prints the value 1
}
five()
But when I paste the same exact code inside Chrome console, the function five() prints 5. Why?
By default JSFiddle wraps your code in the window.onload event, so you're actually running this:
window.onload = function() {
var a = 1;
function five() {
this.a = 5;
console.log(a); //JSfiddle prints the value 1
}
five()
}
That means that a is local to that function, while this still refers to the global object (window). In the Chrome console, without the wrapper function, var a is creating a global variable, which are created and stored as properties on the global object, and is thus the same as window.a / this.a.
If you go to the JavaScript options and choose either of the "nowrap" options, it will log 5 in JSFiddle too:
I would write the code this way to make it work 'everywhere'
var obj = {};
obj.a = 1;
obj.foo = function five() {
this.a = 5;
window.alert(this.a);
}
obj.foo();
I want string convert to variable:
var abc='b';
var b=5;
console.log(window[abc]);
in js, above is normal. when use jquery:
$(document).ready(function(){
var abc='b';
var b=5;
console.log(window[abc]);
});
show is undefined, so, how can I write? In second example, gain 5 through global object.
var abc is defined within a function. So it's a 'local' variable, which isn't in the window object. Just use console.log(abc) and it'll be fine. In your first example console.log(abc) will work as well.
It's all about scopes.
var b = 5;
Exists only in scope of your function(){ ... }, but you are trying to look for it in scope of window.
try this instead:
console.log(eval(abc))
or, assign b as a key to some temp object:
$(document).ready(function(){
var scope = {};
scope.abc = 'b';
scope.b = 5;
console.log(scope[scope.abc])
});
UPDATE
In case you want to use local scope, just replace "scope" with "this":
$(document).ready(function(){
this.abc = 'b';
this.b = 5;
console.log(this[this.abc])
});
For quick example:
$(document).ready(function(){
var abc = 'b';
this.b = 5;
console.log(this[abc]);
});
Can anyone explain to me why "b" returns undefined and how I can get around this problem? Why does the "this" scope get lost when I call prototype functions by reference?
MyClass = function(test) {
this.test = test;
}
MyClass.prototype.myfunc = function() {
return this.test;
}
var a = new MyClass('asd').myfunc();
var b = new MyClass('asd').myfunc;
// Returns "asd" correctly
console.log(a)
// Returns undefined??
console.log(b())
=== EDIT / SOLUTION ===
As plalx writes, the correct solution in my case is to use .bind(). So the result looks like this:
MyClass = function(test) {
this.test = test;
}
MyClass.prototype.myfunc = function() {
return this.test;
}
var a = new MyClass('asd').myfunc();
var b = new MyClass('asd'),
bfunc = b.myfunc.bind(b)
// Returns "asd" correctly
console.log(a)
// Also returns "asd" correctly!
console.log(bfunc())
You need to explicitely bind the this value if you want this behaviour.
var c = new MyClass('asd'),
b = c.myfunc.bind(c);
console.log(b());
By default, this will point to the leftSide.ofTheDot(); in an invocation, or simply the object on which the function was called.
Note: Calling b(); is the same as window.b();.
Binding every function to the object instance is possible but rather inefficient because functions will not get shared across instances anymore.
E.g.
function MyClass(someVal) {
var me = this;
me.someVal = someVal;
me.someFn = function () {
return me.someVal;
};
}
The line var b... is a function reference and you're not actually calling the function.
Here you are assigning to a variable a result of myfunc() function.
var a = new MyClass('asd').myfunc();
And here, you are asigning to b variable function reference, rather then runing it, and assign result to variable.
var b = new MyClass('asd').myfunc;
And finaly here:
console.log(b())
You trying to log result of function b and in that case b() isn't defined anywhere, only it is assigned reference to function.
Try this:
console.log(b); // It logs [Function]
But besides that, your question is hard to understand.
P.S. Use semicolons!