简体   繁体   English

如何在Javascript模块模式中使用私有函数/变量?

[英]How do I use private functions/variables in the Javascript module pattern?

I'm reading this article about the Javascript Module Pattern and came across a snippet which claims you can preserve private variables/functions across module files and access them from each other: 我正在阅读有关Javascript模块模式的这篇文章,并遇到了一个片段,该片段声称您可以跨模块文件保留私有变量/函数,并可以彼此访问它们:

var MODULE = (function (my) {
    var _private = my._private = my._private || {},
        _seal = my._seal = my._seal || function () {
            delete my._private;
            delete my._seal;
            delete my._unseal;
        },
        _unseal = my._unseal = my._unseal || function () {
            my._private = _private;
            my._seal = _seal;
            my._unseal = _unseal;
        };

        // permanent access to _private, _seal, and _unseal

    return my;
}(MODULE || {}));

I'm a little confused as to how I go about implementing this, but I think most of that confusion is from not understanding quite how this works; 我对如何实现此功能有些困惑,但是我认为大部分困惑是由于不完全了解其工作原理。 how does it enable other scripts already loaded to utilize those internal values? 它如何使已经加载的其他脚本利用这些内部值? And how do I add functions and variables within this 'private' space? 以及如何在此“私有”空间中添加函数和变量?

My end goal is to provide a sort of 'abstract' function variable that must be overridden in sub-modules, but still needs referenced in the base module's file. 我的最终目标是提供一种“抽象”功能变量,该变量必须在子模块中被覆盖,但仍需要在基本模块的文件中引用。 Admittedly I haven't played with this much but that's mostly because I'm trying to wrap my head around how the actual implementation works. 诚然,我并没有花太多时间,但这主要是因为我试图围绕实际实现的方式进行研究。

I was thinking of something like the following but it doesn't seem to work as it can't access the internal functions: 我在想类似以下内容的方法,但由于无法访问内部函数,因此似乎无法正常工作:

    // Preserve state of private variables/functions across modules
    var _private = my._private = my._private || {},
        _seal = my._seal = my._seal || function () {
            delete my._private;
            delete my._seal;
            delete my._unseal;
        },
        _unseal = my._unseal = my._unseal || function () {
            my._private = _private;
            my._seal = _seal;
            my._unseal = _unseal;
        };

    my._private._unseal();

    my._private.bindEvents = function () {
        alert("This function should be re-declared in your sub-module.");
    };

    my._private._seal();

Thanks in advance. 提前致谢。

My end goal is to provide a sort of 'abstract' function variable that must be overridden in sub-modules, but still needs referenced in the base module's file. 我的最终目标是提供一种“抽象”功能变量,该变量必须在子模块中被覆盖,但仍需要在基本模块的文件中引用。 Admittedly I haven't played with this much but that's mostly because I'm trying to wrap my head around how the actual implementation works. 诚然,我并没有花太多时间,但这主要是因为我试图围绕实际实现的方式进行研究。

First of all, move forward. 首先,前进。 JavaScript isn't a traditional object-oriented programming language. JavaScript不是传统的面向对象的编程语言。

In JavaScript, if you want to do something if it's defined , you would do this: 在JavaScript中,如果您想执行已定义的操作 ,则可以执行以下操作:

// Look at entire prototype chain for a function
if("doStuff" in obj) {
     obj.doStuff();
}

// Or just check if the own object has the whole function
if(obj.hasOwnProperty("doStuff")) {
     obj.doStuff();
}

As of the thing of private or any visibility on JavaScript, everything you may find around the net is just a trick because currently JavaScript has no access modifiers. 至于私有的或JavaScript的可见性,您在网上可能找到的所有东西只是一个把戏,因为当前JavaScript没有访问修饰符。

Anyway, your sample adds _seal and _private properties to my which usually is called exports , and defines that adding properties to the object set to these top-level properties are private or sealed by convention. 总之,您的样本增加了_seal_private属性来my这通常被称为exports ,并定义添加属性设置为这些顶级属性的对象是私人或按约定密封。 So, yes, it's just a convention: don't access such properties that are part of the object set to _private from outside of the module... 所以,是的,这只是一个约定:不要从模块外部访问属于_private对象的一部分的属性。

BTW, my two cents here is that you should avoid this and use JavaScript as is and deal with the fact that there're no access modifiers. 顺便说一句,我的两分钱是您应该避免这种情况,并按原样使用JavaScript并处理没有访问修饰符的事实。

In the mean time, ECMA-Script 2015 and above have defined a new way to declare properties on which the property name are unique identifiers known as symbols . 同时,ECMA-Script 2015及更高版本定义了一种新的声明属性的方式,该属性名称是唯一的标识符,称为符号 If you don't own the symbol, you can't access the whole property: 如果您不拥有该符号,则无法访问整个属性:

let sampleSymbol = Symbol("sample symbol");
let sampleSymbol2 = Symbol("sample symbol 2");

var obj = {
    // Defines the property with a symbol during object
    // declaration
    [sampleSymbol]: "hello world"
};

// Defines the property using regular property declaration syntax
// once the object has been already built
obj[sampleSymbol2] = "goodbye!";

Now export this object using module pattern and other modules won't be able to access the whole property in an easy way, which in turn works well to simulate property access private modifier. 现在,使用模块模式导出该对象,其他模块将无法轻松访问整个属性,这反过来又可以很好地模拟属性访问private修饰符。

The worst part is you can still get a given object symbols using Object.getOwnPropertySymbols function, but symbols aren't part of an iterator like Array.prototype.forEach(...) , for..in , Object.keys(...) , or for..of , so you should go for it. 最糟糕的是,你仍然可以得到使用给定对象的符号Object.getOwnPropertySymbols功能,但符号不是像一个迭代器的一部分Array.prototype.forEach(...) for..inObject.keys(...)for..of ,因此您应该争取。

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

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