用于创建单例或保持变量引用的JavaScript方法

有时像这样的技术用于保持变量引用或创建单例.这样我们只会调用一次createVariable.

这种方法的优点和缺点是什么?

function createVariable() {
    // usually here may be some long asynchronous task
    // 
    return true;
}

function useVariable() {
    if(!useVariable.someVar) {
        useVariable.someVar = createVariable();
    }

    // do something with useVariable.someVar 
}

// we will call useVariable several times. 
// The idea is to call createVariable 
// one time only. 
useVariable();
useVariable();
useVariable();

我很感谢所有的想法和建议.我不想创建一个单身人士.只想在功能级别保持变量引用.没有
污染全球范围.

最佳答案

What are the pros and cons of this approach?

这种方法没问题,尽管我质疑它是否需要更高级别的设计问题.

实施有几个问题:

>如果someVar包含falsey值,则在不应该的时候重新创建它.要检查您之前是否已创建它,请使用if(!useVariable.hasOwnProperty(“someVar”)){而不是if(!useVariable.someVar){.

falsey值为0,“”,NaN,undefined,null,当然还有false. (所有其他值都是“真实的”.)
>函数有一些内置属性,包括它们自己的(名称,长度)和它们从原型获得的属性(主要是各种方法).因此,如果您的变量具有名称,长度,调用等名称,那么您将错误地认为您已经创建了它们,因为createVariable已经具有带有truthy值的属性(在您的createVariable情况下).您可以通过添加某种类型的前缀或使用单独的对象作为映射来解决这个问题(尽管对象也继承了属性,因此您仍然可能需要前缀),或者如果您使用的是ES2015,则可以使用一张地图.

你曾经说过你只想创建一次变量并且“不污染全局范围”(这是一件好事可以避免).我只需将我的代码包装在作用域函数中即可:

(function() {
    var someVar = createSomeVar();

    // My other code here
})();

这使得全局命名空间保持不变,并且只创建someVar的单个副本,而不需要任何特定的管道.

点赞