简体   繁体   English

了解模块的Javascript范围

[英]Understanding Javascript scope with modules

I am trying to understand how scope works with node modules. 我试图了解范围如何与节点模块一起工作。 I have an IIFE to initialize a LinkedList, which uses Node object for each element. 我有一个IIFE来初始化一个LinkedList,它为每个元素使用Node对象。
using IIFE to avoid polluting global scope 使用IIFE避免污染全球范围

After IIFE, where does the Node go? 在IIFE之后,Node会去哪里? Is there any way I can access Node in require object ie test class? 有什么方法可以访问require对象(即测试类)中的Node?

linkedList.js 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 linkedListTest.js

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

// Can I access Node here?

Generally, any functions and variables defined in your ES6 module are module scoped, ie your IIFE is not necessary in this case. 通常,ES6模块中定义的任何函数和变量都是模块范围的,即在这种情况下不需要IIFE。 Node or insert will not be accessible from outside the module unless they are explicitly exported via module.exports . 除非通过module.exports显式导出Nodeinsert否则无法从模块外部对其进行访问。


With that in mind, unit tests won't be able to simply access the implementation details either. 考虑到这一点,单元测试也将无法简单地访问实现细节。 If you want to test Node separately, the cleanest way would likely to move it to a separate module and import it into LinkedList : 如果要单独测试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');
// ...

The only things accessible outside of the Node module are those added to the module.exports variable. 在Node模块之外只能访问的是添加到module.exports变量中的东西。

When you do 当你做

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

x will be equal to the module.exports variable defined in ./some/path.js . x是等于module.exports中定义的变量./some/path.js

Unless Node is somehow made explicitly available in your module.exports object, you cannot access it from outside the module file. 除非以某种方式使Nodemodule.exports对象中显式可用, module.exports您将无法从模块文件外部访问它。

The typical way to define modules with an IIFE in Node is to do: 在Node中使用IIFE定义模块的典型方法是:

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

But you don't really need the IIFE. 但是您实际上并不需要IIFE。 Unlike a browser environment, stuff only gets added to the global scope in node if you explicitly request that by saying 与浏览器环境不同,仅当您通过以下方式明确请求时,才将内容添加到节点的全局范围中

global.variable = something;

Otherwise, your variable is in module-local scope. 否则,您的变量在模块本地范围内。 As Node treats modules and files as being in one-to-one correspondence, this means any variables you create within a file are only accessible within that file - barring the use of global and module.exports . 由于Node将模块和文件视为一一对应,这意味着您在文件中创建的任何变量都只能在该文件中访问,除非使用globalmodule.exports

You're scope is already contained within the module - except for what you choose to export, so you don't really need the IIFE. 您的范围已经包含在模块中-除了您选择导出的范围外,因此您实际上并不需要IIFE。

If you wanted it to work with an IIFE, you would have to attach the IIFE to module.exports rather than wrapping your IIFE around it. 如果希望它与IIFE一起使用,则必须将IIFE附加到module.exports而不是将IIFE包裹在它上面。 Something like... 就像是...

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM