【问题标题】:Is it possible to get a different scope for a required file?是否可以为所需文件获得不同的范围?
【发布时间】:2017-07-11 14:20:29
【问题描述】:

假设我有这个名为 import.js 的示例文件

var self;
function Test(a,b){
   this.a = a;
   this.b = b;
   self = this;
}
Test.prototype.run = function(){
   console.log(self.a, self.b)
}
module.exports = Test

当我需要该文件并创建一个新的“对象”时,一切正常,但是当我创建第二个对象时,它们都可以访问自己,只有后一个有效。

var Test = require('./import.js');

var one = new Test(1,2);
one.run()
1 2

var two = new Test(3,4);
two.run()
3 4
one.run()
3 4

有没有办法重新要求文件以创建单独的范围?

把它当作两个不同的变量是行不通的,

var Test1 = require('./import')
var Test2 = require('./import')
var one = new Test1(1,2);
var two = new Test2(3,4);
one.run()
3 4

但是复制文件正是我想要的......

var Test1 = require('./import1');
var Test2 = require('./import2');
var one = new Test1(1,2);
var two = new Test2(3,4);
one.run();
1 2

是的,将self 重写为this 会起作用,但是,这是否可以在不修改或复制 import.js 文件的情况下实现?

【问题讨论】:

    标签: javascript node.js scope closures


    【解决方案1】:

    简而言之,不修改import.js文件或复制文件是不可能做到这一点的。这是因为self 是该文档的全局变量,对于函数对象的每个实例都是相同的。

    备选方案#1

    问题是您将self 分配给了一个全局变量。这两者都可以访问相同的变量,因此您可以获得观察到的结果。此外,您对 self 的使用是不必要的。下面的代码按照您的描述工作。

    function Test(a,b){
       this.a = a;
       this.b = b;
    }
    Test.prototype.run = function(){
       // Simply using 'this' to access the properties of the function is sufficient - no need for self
       console.log(this.a, this.b)
    }
    module.exports = Test
    

    Working example

    在这种情况下,对于每个 new Test() 实例,您将拥有一个单独的实例,因此您无需“重新要求”这些文件。

    备选方案#2

    如果您想根据您的编辑保留self,另一种选择是只重写您要调用的函数。例如:

    var Test = require('./import.js');
    
    Test.prototype.run = function(){
       console.log(this.a, this.b)
    }
    

    如果这也不是一个选项,那么您需要提供更多信息,说明您可以做什么或不能做什么。

    【讨论】:

    • 对于每个 new Test() 实例,您将拥有一个单独的实例,因此您无需“重新要求”文件
    • "是否可以在不修改 import.js 文件或复制它的情况下以某种方式做到这一点?"
    • 不可能,因为JS语言的特性。我已经更新了我的答案以包括这个。
    • 虽然这不能完全回答问题,但它解决了根本问题。 JavaScript 模块以它们的方式工作是有原因的。以 OP 要求的方式对待他们是一种反模式。
    • @lonewarrior556 添加了备选方案 #2,因此您不必修改 import.js 文件。
    【解决方案2】:

    在这里回答我自己的问题,但至少有两种方法是可能的......

    (1) 删除缓存

    How to remove module after "require" in node.js?

    var Test1 = require('./import.js');
    delete require.cache[require.resolve('./import.js')]
    var Test2 = require('./import.js');
    
    var one = new Test1(1,2);
    var two = new Test2(3,4);
    
    one.run()
    1 2
    two.run()
    3 4
    

    看起来甚至没有那么凌乱,尽管它效率极低,而且以这种方式编写代码会很快变得昂贵......


    (2) 使用函数作用域

    因为 require 读取文件然后运行它,

    var Test = require('./test.js');
    

    等价于

    var Test = eval( fs.readFileSync('./test.js', 'utf8') );
    

    因此,如果您不使用 require,而是读取文件,您可以在函数内部建立新的范围:

    var fs = require('fs');
    var File = fs.readFileSync('./import.js', 'utf8');
    var Test1, Test2;
    (function(){ Test1 = eval(File); })();
    (function(){ Test2 = eval(File); })(); 
    

    文件中的 self 现在将存储在您创建的函数范围内。所以再一次:

    var one = new Test1(1,2);
    var two = new Test2(3,4);
    
    one.run()
    1 2
    two.run()
    3 4
    

    稍微麻烦一些,但比每次删除缓存并重新读取文件要快得多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-29
      • 2013-06-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多