如何创建多个IIFE Javascript模块实例?

4
我正在处理一个庞大的 JavaScript 代码库,试图对其进行重新组织。我并不是专家,刚开始学习良好的 JavaScript 编码实践。所以,我想做的一件事是将所有代码分成模块。在这个特定的例子中,我正在尝试创建一个模块,帮助我优化视频嵌入。我想传递一个 id 给模块,并从中获得一些 HTML 代码或图像。我没有把整个代码放在这里,但这已经足够作为示例了。
var videoIframe = (function($) {
    'use strict';
     var id,

    setVideoId = function(videoId) {
        id = videoId;
        console.log(id);
    },
    getVideoThumbnail = function(videoId) {
        setVideoId(videoId);

    },
    test = function() {
        console.log(id)
    },
    getVideoEmbedCode = function() {

    };

    return {
       test: test,
       getVideoThumbnail: getVideoThumbnail
    };
})(jQuery);

在另一个模块中,我将其分配给两个变量:
    var video1 = videoIframe;
    var video2 = videoIframe;

    video1.getVideoThumbnail(123);
    video2.getVideoThumbnail(456);

    video1.test();
    video2.test();

当然,我没有得到我期望的结果。在第二个 getVideoThumbnail 调用之后,它总是打印 456
经过一些调查,我明白了我正在创建一个单例,即一个单一实例,并且我只在该实例内更改值。我认为我需要为我的模块创建一个构造函数,但我不确定如何与 IIFE 模式结合使用。这是否是正确的方法?
4个回答

6

这是正确的做法吗?

不是。立即调用函数表达式(IIFE)是用于只需执行一次的操作。

如果您需要多次执行某个操作,则应使用常规函数,并多次调用它。

var videoIframe = (function($) {

    function videoIframe() {
        'use strict';
        var id,

            setVideoId = function(videoId) {
                id = videoId;
                console.log(id);
            },
            getVideoThumbnail = function(videoId) {
                setVideoId(videoId);

            },
            test = function() {
                console.log(id)
            },
            getVideoEmbedCode = function() {

            };

        return {
            test: test,
            getVideoThumbnail: getVideoThumbnail
        };
    }

    return videoIframe;
})(jQuery);

var video1 = videoIframe();
var video2 = videoIframe();

video1.getVideoThumbnail(123);
video2.getVideoThumbnail(456);

video1.test();
video2.test();

那么为什么你还要在你的示例中保留IIFE呢? - Carlo
1
@Carlo — 因为还有一些事情需要完成(即使让 $ 变量可用)。需要重复调用的代码被移动到自己的函数中,并从 IIFE 中返回。 - Quentin

1
问题在于你在将对象赋值给videoIframe变量时进行了初始化:
var videoIframe = (function($) {
  // ...
})(jQuery);

你可以尝试使用以下代码:
var videoIframe = (function($) {
  // ...
});

var video1 = videoIframe(jQuery);
var video2 = videoIframe(jQuery);

1

我做了一些小的修改。希望对你有用。

    var videoIframe = (function($) {
    'use strict';
     var id;

    function _setVideoId(videoId) {
        id = videoId;
        alert(id);
    };
    function _getVideoThumbnail(videoId) {
        _setVideoId(videoId);

    };
    function _test(){
        console.log(id)
    }
    function _getVideoEmbedCode() {

    };

    return {
       test: _test,
       getVideoThumbnail: _getVideoThumbnail
    };
})(jQuery);

现在你可以这样调用

 videoIframe.getVideoThumbnail(123);
 videoIframe.getVideoThumbnail(561);

jsfiddle

的中文翻译为:

{{链接1:jsfiddle}}


1

只需将videoIframe保留为返回IIFE的函数,而不是重用单例。我保留了IIFE,以便ID和内部函数继续被封装,因此,如果它们不在返回的接口对象中,则无法访问。如果您计划创建很多这样的对象,则使用构造函数和原型可能更有效,因此内部函数不会为每个实例重新创建。

var videoIframe = function() {
    'use strict';
    return (function() {
        var id,
            setVideoId = function(videoId) {
                id = videoId;
                console.log(id);
            },
            getVideoThumbnail = function(videoId) {
                setVideoId(videoId);

            },
            test = function() {
                console.log(id)
            },
            getVideoEmbedCode = function() {

            };          
        return {
           test: test,
           getVideoThumbnail: getVideoThumbnail
        };
    }());
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接