当模块中的变量更改时,所需模块不会更新

时间:2018-11-21 19:11:34

标签: javascript node.js

我有一个javascript文件,其中我需要另一个文件,该文件的变量会发生变化。

main.js

let num = require("./extra").num

extra.js

let num = 5;

setInterval(() => {
  if (num > 0) {
    num--;
  }
  console.log(num);
}, 1000);

module.exports = {
  num
};

现在在main.js文件中,变量num始终为5,并且永不更改。我需要怎么做才能使其始终保持更新?

注意:在变量更改后,我要在main.js中声明该变量,因此它不应为5

5 个答案:

答案 0 :(得分:0)

require()main.js开始运行时(即在第一个setInterval()触发器之前)进行评估,因此require("./extra").num始终返回5

此外,由于num是通过module.exports中的值传递的,因此重复调用require()不会有帮助。

一种可行的(不确定最好的方法)是:

let num = 5;

setInterval(() => {
  if (num > 0) {
    num--;
  }
  console.log(num);
}, 1000);

function getNum() {
  return num;
}

module.exports = {
  getNum
};

然后

let num = require("./extra").getNum()

答案 1 :(得分:0)

这将起作用:

extra.js中:

let num = 5;

setInterval(() => {
  if (num > 0) {
    num--;
  }
  console.log("in extra: " + num);
}, 1000);

module.exports = {
  getNum: function() {
    return num;
  }
};

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);

由于main.js中的打印语句每秒输出一次,因此您会注意到require('./extra').getNum()的每个新调用都会获得新的递减值。

答案 2 :(得分:0)

关于此问题的另一种观点:将信息存储在变量中并传递给变量时,您正在处理“值”和“引用”之间的差异。

原语按值(字符串,数字,布尔值)传递。 更复杂的结构通过引用(对象,数组,函数)传递。

有什么区别?

按值传递:

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)

在此示例中,b并不继承赋值期间的所有属性(var b = a),仅继承其值。这实质上就是您发布的代码中发生的事情。由于num是基元,因此当您为其分配值时,仅传递其值 。这实际上发生在两个地方:

module.exports = {
  num
}

let num = require("./extra").num

在这两种情况下,都声明了一个变量(或在module.exports中进行了重新分配,并为其分配了num的值,这是一个原始值。现在,这些变量和/或对象属性已“锁定在“可以这么说,除非在代码中的其他位置手动将它们重新分配为其他值。

通过引用传递:

我在上面所说的“复杂结构”,就像一个对象,实际上(以一种简单的陈述方式)是指向内存中某个位置的指针,该位置包含对其他对象的引用值(又称属性/方法)。如果听起来很抽象,那是因为。每次创建对象时,JavaScript引擎都会在内存中保留另一个位置,以收集和引用该对象的属性。这会创建一些有趣的场景,例如:

const a = {}
const b = {}

console.log(a === b) // false!
console.log(a == b) // also false!

即使我们查看了这些对象并说它们看起来是相同/相等的,它们实际上都是对内存中位置的引用,而在内存中是两个不同位置,因此它们不能相同。但是,如果我们将两个变量都分配到内存中的同一位置,它们将总是相等(这里是您问题的解决方案):

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 }

如您所见,既然两个变量都指向内存中的相同位置(const b = a),它们将始终“共享”相同的属性,因此,这些属性的值相同。

我希望这会有所帮助,这是解决您原来问题的以下原理的一种实现方式(可能不建议其他人推荐的单例“ getNum”选项,但肯定同样可行):

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

祝您编程愉快!

答案 3 :(得分:0)

您不能使用简单的整数值来执行此操作,因为它作为值而不是作为引用传递。但是你可以用一个对象来代替

main.js

let num = require("./extra").num

setInterval(function(){
    
 console.log(num.value); // print 1, 2, 3

}, 1000);

额外的.js

module.exports.num = {value: 0};

setInterval(function(){

    exports.num.value++;

}, 1000);

答案 4 :(得分:0)

做一个不同的答案。如果您想保留 num 而不是 getNum(),您可以使用带有 setter 和 getter 的类来表示 num。例如:

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);

输出

5
3
0
1000

警告:您不会破坏 setInterval,因此您的代码永远不会结束。