使用模块了解Javascript范围

时间:2017-03-30 18:11:56

标签: javascript node.js module

我试图了解范围如何与节点模块一起工作。我有一个IIFE来初始化一个LinkedList,它为每个元素使用Node对象 使用IIFE避免污染全球范围

在IIFE之后,节点在哪里?有什么办法可以在require对象即测试类中访问Node吗?

linkedList.js



(function LinkedListInit() {
    module.exports = new LinkedList();

    function LinkedList() {
        this.head;
    }

    // LinkedList Node
    function Node(data, next) {
        this.data = data;
        this.next = next;
    }

    LinkedList.prototype.insert = insert;

    function insert(data) {
        var curr = this.head,
            newNode = new Node(data);
            
        if (this.head == null) {
            this.head = newNode;
        } else {
            while (curr.next != null) {
                curr = curr.next;
            }
            curr.next = newNode;
        }
        return this;
    }
}());




linkedListTest.js

var linkedList = require('../../js/ds/linkedList');
// Test cases for linkedList.insert(val); works fine.

// Can I access Node here?

3 个答案:

答案 0 :(得分:3)

通常,ES6模块中定义的任何函数和变量都是模块范围的,即在这种情况下不需要IIFE。除非通过Node明确导出,否则无法从模块外部访问insertmodule.exports

考虑到这一点,单元测试也无法简单地访问实现细节。如果您想单独测试Node,最干净的方式可能会将其移至单独的模块并将其导入LinkedList

// Node.js
function Node(data, next) {
    this.data = data;
    this.next = next;
}

module.exports = Node;


// LinkedList.js
var Node = require('./Node');

function LinkedList() {
    this.head;
}
LinkedList.prototype.insert = function(data) {
    var curr = this.head,
        newNode = new Node(data);

    if (this.head == null) {
        this.head = newNode;
    } else {
        while (curr.next != null) {
            curr = curr.next;
        }
        curr.next = newNode;
    }
    return this;
}

module.exports = LinkedList;


// NodeTest.js
var Node = require('./Node');

var node = new Node('foo');
// ...


// LinkedListTest.js
var LinkedList = require('./LinkedList');

var linkedList = new LinkedList();
linkedList.insert('foo');
// ...

答案 1 :(得分:1)

在Node模块之外可以访问的唯一内容是添加到module.exports变量的内容。

当你这样做时

var x = require('./some/path');

x将等于module.exports中定义的./some/path.js变量。

除非在Node对象中以某种方式明确提供module.exports,否则无法从模块文件外部访问它。

在Node中使用IIFE定义模块的典型方法是:

module.exports = (function() {
    //...a lot of code...
    return { 
      exportedValue1: somethingIWantToBeAvailable;
      exportedValue2: aDifferentThing;
      //... and so on ...
    };
})();

但你真的不需要IIFE。与浏览器环境不同,如果显式地请求

,则只会将东西添加到节点中的全局范围内
global.variable = something;

否则,您的变量位于 module-local 范围内。由于Node将模块和文件视为一一对应,这意味着您在文件中创建的任何变量只能在该文件中访问 - 禁止使用globalmodule.exports

答案 2 :(得分:1)

您的范围已包含在模块中 - 除了您选择导出的内容,因此您不需要IIFE。

如果您希望它与IIFE一起使用,则必须将IIFE连接到module.exports,而不是将IIFE包裹在其周围。有点像...

module.exports = (function LinkedListInit() {   
    function LinkedList() {
        this.head;
    }        
    return new LinkedList();
// ...