首页 > 解决方案 > 在不同文件中导入相同的 javascript 模块,共享相同的词法范围

问题描述

所以我有这个文件叫做“fruits.js”

在这个模块中,我有一个值为“apples”的全局变量“name”,我也有一个用于该变量的 getter 和 setter,以获取变量 name 的值并为其设置新值。

现在我将此模块导入到一个名为“client1.js”的文件中,然后运行 ​​getter,它显示“apples”。

现在我用值“coconuts”运行 setter 并更改了变量。

现在在 client1.js 完成执行后,client2.js 使用相同的复制代码开始执行。

而不是“苹果”,而是显示“椰子”。

所以我的问题是,同一个模块的多个导入是否共享相同的词法范围?

代码 -

// fruits.js
let fruit = "apples";

const set = () => {
    let flower = "lily";


    const setfruit = (newfruit) => {
        fruit = newfruit;
    }

    const getfruit = () => {
        return fruit;
    }

    const setflower = (newflower) => {
        flower = newflower;
    }

    const getflower = () => {
        return flower;
    }

    return {
        setfruit,
        getfruit,
        setflower,
        getflower
    }
}

module.exports = set();


// client1.js
const fruitsnflowers = require("./closure.js")

const execute = () => {
    console.log(fruitsnflowers.getfruit())
    console.log(fruitsnflowers.getflower())
    
    fruitsnflowers.setfruit("coconut")
    fruitsnflowers.setflower("hibiscus")
}

module.exports = execute;

// client2.js
const fruitsnflowers = require("./closure.js")

const execute = () => {
    console.log(fruitsnflowers.getfruit())
    console.log(fruitsnflowers.getflower())
    
    fruitsnflowers.setfruit("papaya")
    fruitsnflowers.setflower("lotus")
}


module.exports = execute;


// driver.js
const client1 =  require("./client1.js")
const client2 =  require("./client2.js")

client1()
client2()


// output
~ node driver.js
apples
lily
coconut
hibiscus

标签: javascriptnode.js

解决方案


模块的代码仅在首次导入时加载和初始化一次。之后,从后续尝试导入它时会返回完全相同的模块句柄。

因此,在您的情况下,当您这样做时module.exports = set(),您正在运行该函数,该函数set()返回一个对象,该对象具有对可以看到本地范围的本地函数的引用。导入该函数的任何人都将获得完全相同的导出对象,因此,它们都将指向相同的本地范围(在此模块内)。

如果您setFruit("banana")从 moduleA 中调用,然后getFruit()从 moduleB 中调用,您将返回"banana". fruits 模块只有一组状态和一个内部fruits变量,所有调用它的导出方法都可以访问。

所以我的问题是,同一个模块的多个导入是否共享相同的词法范围?

您在这里使用术语“词法范围”有点令人困惑。导入另一个模块的两个模块都有自己的词法范围,但是导入模块中的代码位于自己的范围内,无论谁导入它都不会改变。

因此,如果 moduleA 和 moduleB 都导入您的 fruits 模块,那么将有三个范围,因为每个模块在顶层都有自己的词法范围。当您调用水果函数时,该函数在水果词法范围内内部(在函数执行内部)运行。当您从模块A 或模块B 中取回返回值时,您就在这些模块的范围内进行操作。范围没有混合。每个模块都有自己的顶级范围。


推荐阅读