将“new”关键字用作“static”的Javascript函数表达式是否正确?

IT技术 javascript
2021-01-26 07:18:00

我只是想更深入地了解 Javascript。

我创建了一个“类” gameData,我只想要其中一个,不需要构造函数或实例化。

所以我像这样创造了它......

var gameData = new function () {

    //May need this later 
    this.init = function () { 
    };

    this.storageAvailable = function () {
        if (typeof (Storage) !== "undefined") {
            return true;
        }
        else {
            return false;
        }
    };
}

意识到'new'关键字不允许它被实例化并使其可用,就像C#中的静态类一样。

我是否正确地考虑了这一点?作为静态?

3个回答

不,它不是静态的,因为它仍然具有constructor指向您的“匿名”功能属性。在您的示例中,您可以使用

var gameData2 = new (gameData.constructor)();

重新实例化第二个对象,因此“类”(实际上是实例)并不是真正的“静态”。您基本上是在泄漏构造函数,也可能是在泄漏与其绑定的数据。此外,一个无用的原型对象 ( gameData.constructor.prototype) 确实被创建并插入到 的原型链中gameData,这不是您想要的。

相反,您可以使用

  • 一个简单的对象字面量(如Daff 的回答)。这意味着您没有构造函数,没有闭包范围的私有变量(无论如何您都没有使用过),也没有(自定义)原型。
  • (揭示)module模式(如jAndy 的回答)。在那里你有一个IIFE来创建闭包范围的变量,并且可以返回任何类型的对象。
  • 一个实际的构造函数(“类”),可以稍后(在需要时)实例化,并始终产生相同的单例对象。

这就是单例模式的样子:

function GameData() {
    if (this.constructor.singleton)
        return this.constructor.singleton;
    else
        this.constructor.singleton = this;

    // init:
    // * private vars
    // * public properties
    // ...
}
GameData.prototype.storageAvailable = function () {
    if (typeof (Storage) !== "undefined") {
        return true;
    }
    else {
        return false;
    }
};

var gameData = new GameData();
var gameData2 = new GameData();
gameData === gameData2 === GameData.singleton; // true

然而,原型是非常无用的,因为您只有一个GameData. 只有继承才会变得有趣。

ECMAscript 中没有Class,只有Object

new用于调用一个函数时,我们称它为构造函数这个函数在完成后有点自动返回一个新对象。使用this(引用该新创建的对象)存储在该对象中的任何数据都将作为该对象的属性返回。除此之外,为这个函数new设置一个名为constructor的属性

在您的情况下,您甚至不需要使用new,您可以轻松地重新编写代码,如下所示:

var gameData = (function () {
    var public = { },
        private = { }; // any private data can get stored here

    //May need this later 
    public.init = function () { 
    };

    public.storageAvailable = function () {
        if (typeof (Storage) !== "undefined") {
            return true;
        }
        else {
            return false;
        }
    };

    return public;
}());

这称为工厂模式单例模式module模式,可能还有其他一些名称。

@toddv:一个很好的建议和推荐是 Douglas Crockford 的“JavaScript:好的部分”,用于进入 ECMAscript 继承、对象 + 原型。
2021-03-18 07:18:00
您应该称其为“自调用匿名工厂”。
2021-03-21 07:18:00
这不是同一件事的更简洁的语法吗?- “类实际上是函数” developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes
2021-03-22 07:18:00
谢谢!这看起来很有趣……还有更多让我尝试和消化的东西!:)
2021-03-23 07:18:00
There is no Class in ECMAscript. 实际上,现在有了 ES6。
2021-04-02 07:18:00

我认为您正在寻找的只是一个简单的 JavaScript 对象:

var gameData = {
    //May need this later 
    init : function () { 
    },

    storageAvailable : function () {
        if (typeof (Storage) !== "undefined") {
            return true;
        }
        else {
            return false;
        }
    }
}

如果要使用私有变量,请创建一个揭示module模式样式的包装器。这基本上是 jAndy 建议的:

var gameData = (function() {
    var private = 'private variable';

    return {
        //May need this later 
        init : function () { 
        },

        storageAvailable : function () {
            if (typeof (Storage) !== "undefined") {
                return true;
            } else {
                return false;
            }
        }
    }
})();
我更新了私有变量的答案。我不明白为什么你需要一个静态类的构造函数?
2021-03-21 07:18:00
我没有走这条路,因为我想拥有公共和私有方法和构造函数……而这不能使用对象文字来完成……对吗?
2021-04-03 07:18:00