I have a javascript file and in it I require another file that has a variable that changes.
main.js
let num = require("./extra").num
extra.js
let num = 5;
setInterval(() => {
if (num > 0) {
num--;
}
console.log(num);
}, 1000);
module.exports = {
num
};
Now in the main.js file that variable num is always 5 and never changes. What do I need to do to get it updated all the time?
Note: I'm declaring the variable in main.js AFTER the variable changes so it shouldnt't be 5
I have a javascript file and in it I require another file that has a variable that changes.
main.js
let num = require("./extra").num
extra.js
let num = 5;
setInterval(() => {
if (num > 0) {
num--;
}
console.log(num);
}, 1000);
module.exports = {
num
};
Now in the main.js file that variable num is always 5 and never changes. What do I need to do to get it updated all the time?
Note: I'm declaring the variable in main.js AFTER the variable changes so it shouldnt't be 5
Share Improve this question asked Nov 21, 2018 at 19:11 PeciusPecius 851 silver badge5 bronze badges 2-
In regards to your note, how is the variable changing? With your current code, I believe if you do a new
require
statement, it'll create a new instance of thenum
in your extra.js. So the one that was changed before, is no longer the one that is being accessed now. – natn2323 Commented Nov 21, 2018 at 19:20 - In setInterval the variable gets decremented. So if it does that, when I require it it shouldnt be the default 5 – Pecius Commented Nov 21, 2018 at 19:29
5 Answers
Reset to default 4 +500This will work:
in extra.js
:
let num = 5;
setInterval(() => {
if (num > 0) {
num--;
}
console.log("in extra: " + num);
}, 1000);
module.exports = {
getNum: function() {
return num;
}
};
in main.js
:
let num = require('./extra').getNum();
console.log("initial value is: " + num);
setInterval(() => {
let num = require('./extra').getNum();
console.log("in main loop: " + num);
}, 1000);
Since the print statements in main.js
output every second, you'll notice that every new call of require('./extra').getNum()
will get the newly decremented value.
Another perspective on this problem: you are dealing with the difference between "value" and "reference" when storing information in a variable and passing it around.
Primitives are passed by value (strings, numbers, booleans). More plex structures are passed by reference (Objects, Arrays, Functions).
What is the difference?
Pass by value:
let a = 3
let b = a
console.log(a) // 3
console.log(b) // 3
a = 4
console.log(a) // 4 (obviously)
console.log(b) // 3 (when we assigned b = a, b was assigned to the value of a, which at the time was 3)
In this example, b
does not inherit all of the properties of a during that assignment (var b = a
), only it's value. This is essentially what is happening in the code you posted. Because num is a primitive, when you assign values to it, only it's value at the time is passed along. This actually happens in two places:
module.exports = {
num
}
and
let num = require("./extra").num
In both instances, a variable is declared (or reassigned, in the case of module.exports, and assigned the value of num
which is a primitive. Now those variables and/or object properties are "locked in" so to speak, unless they are manually reassigned elsewhere in the code to a different value.
Pass by Reference:
What I referred to above as a "plex structure," like an Object, is (in perhaps a simplistic way of stating things) essentially a pointer to a place in memory that contains references to other values (a.k.a. properties/methods). If that sounds abstract, that's because it is. Every time an object is created, the JavaScript engine reserves another place in memory for that object's properties to be collected and referenced. This creates some interesting scenarios, like:
const a = {}
const b = {}
console.log(a === b) // false!
console.log(a == b) // also false!
Even though we look at those objects and would say they appear to be identical/equal, they are actually both just references to places in memory, and two different places in memory, so they cannot be the same. However, if we assign both variables to the same location in memory, they will always be equal (and herein is the solution to your problem):
const a = {}
const b = a
console.log(a === b) // true!
console.log(a == b) // also true!
a.prop = 4
console.log(b) // { prop: 4 }
b.prop = 2
b.other = 3
console.log(a) // { prop: 2, other: 3 }
As you can see, now that both variables point to the same place in memory (const b = a
), they will always "share" the same properties and therefore, the same values of those properties.
I hope that was helpful, and here is an implementation (probably not preferred to the singleton "getNum" option remended by others, but certainly equally viable) of these principles that solves your original problem:
index.js
const obj = require('./num')
console.log(obj.num)
setTimeout(() => console.log(obj.num), 2000)
setTimeout(() => console.log(obj.num), 4000)
setTimeout(() => console.log(obj.num), 6000)
num.js
const obj = { num: 5 }
setInterval(() => {
if (obj.num > 0) {
obj.num--
}
}, 1000)
module.exports = obj
Happy coding!
require()
is evaluated when the main.js
begins to run (i.e. before the first setInterval()
triggers), so require("./extra").num
always return 5
.
Also since num
is passed by value in module.exports
, repeatedly calling require()
won't help.
A working (not sure if best) way to do it would be:
let num = 5;
setInterval(() => {
if (num > 0) {
num--;
}
console.log(num);
}, 1000);
function getNum() {
return num;
}
module.exports = {
getNum
};
then
let num = require("./extra").getNum()
You cannot do this with simple integer value as it passes as value and not as reference. But you can use an object instead
main.js
let num = require("./extra").num
setInterval(function(){
console.log(num.value); // print 1, 2, 3
}, 1000);
extra.js
module.exports.num = {value: 0};
setInterval(function(){
exports.num.value++;
}, 1000);
To make a diff answer. If you want keep the num
and not getNum()
you could use a class with setter and getter for num
. For example:
extra.js
module.exports = new class ExtraContainer {
constructor() {
this._num = 5;
// Do stuff...
setInterval(() => {
if (this._num > 0) {
--this._num;
}
// console.log(this._num);
}, 1000);
}
get num() {
return this._num;
}
set num(value) {
// Do nothing...
}
}
index.js
const extra = require("./extra");
console.log(extra.num);
// 2 sec timeout
setTimeout(() => {
console.log(extra.num);
}, 2000);
// 5 sec timeout
setTimeout(() => {
extra.num = 1000; // The user cant modify the variable
console.log(extra.num);
}, 6000);
// 7 sec timeout
setTimeout(() => {
extra._num = 1000; // You can avoid this with diff teqniques
console.log(extra.num);
}, 7000);
output
5
3
0
1000
WARNING: You don't destroy the setInterval
, so your code never ends.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745663199a4638962.html
评论列表(0条)