IIFE创建模式-但如何支持构造函数参数

IIFE creation pattern - but how to support constructor parameters?

本文关键字:支持 构造函数 参数 何支持 模式 创建 IIFE      更新时间:2023-09-26

作为一名长期的经典继承OO程序员,我对构造函数的使用和创建接受所需参数作为构造函数参数的对象非常熟悉。例如,发送与订单相关的警报的对象可能看起来像:

var orderNotifier = function(orderId, notifier, recipients)
{
    this.notifyApproved = function()
    { 
        // use the notifier object passed as ctor param to send notifications 
        // related to orderId to recipients 
    }
    this.notifySomeOtherEvent = function() { // use the ctor params again }
}
//  then use it like
var on = new orderNotifier(12345, new BasicNotifier(), someArrayOfEmails);
on.notifyApproved();

因此,这是一个人为的例子,但举例说明了(IMHO)参数化构造函数的值。具体而言:

  1. 在单个语句中将状态传递给对象
  2. 简化的方法签名
  3. 内部状态隐藏

意识到JavaScript中的构造函数创建模式不太支持信息隐藏,我被立即调用函数表达式(IIFE)模式所吸引,该模式具有闭包和更强的访问控制。现在我遇到了这样一个事实,即我不能使用IIFE模式传递对象构造参数,或者至少我不明白如何才能传递。

我知道你可以把参数传递给匿名函数,比如:

(function(param){})(someVar);

但这与显式创建新对象并将参数传递给构造函数不同。根据IIFE模式的本质,我还不一定有要传递给对象的数据。

我的IIFE版本的上面想要:

var orderNotifier = (function()
{
    var privateHelperMethod = function() { return 'blahblahblah'; };
    return {
        notifyApproved: function(orderId, notifier, recipient)
        { 
            // use the notifier object passed as ctor param to send notifications 
            // related to orderId to recipients
            var msg = privateHelperMethod() 
        },
        notifySomeOtherEvent: function(orderId, notifier, recipient)
        {
            // use the ctor params again
            var msg = privateHelperMethod();
        }
    };
}}();

因此,我必须询问经验丰富、进步的JavaScript专业人士:使用标准ECMAScript 5语言功能,使用IIFE模式创建对象并在单个操作中提供对象状态的最佳实践(甚至可能只是一种常见实践)是什么?(除了公开setState()或类似方法之外。)换句话说:我怎么能既吃蛋糕又吃蛋糕呢?

您的IIFE构造函数模式创建了一个singleton(始终只有一个对象)。它没有公开构造函数,因此不能用于创建更多对象。因此,您可以通过IIFE的参数将任何想要的信息传递到单例中,或者直接将这些参数编码到实现中。

这就是为什么我想让你向我们展示你真正谈论的设计模式,因为这个特定的模式不是通用的构造函数,也不是为创建多个对象而设计的。它创建了一个singleton对象。这就是它的最佳用途。如果返回的对象公开了可以用作构造函数的函数,那么它们可以像其他构造函数一样接受参数。

我认为这里没有问题。我看不出有什么问题需要解决。

根据您的评论,如果您想将非静态数据传递到IIFE,那么您必须在创建非静态数据后定位IIFE(以便在IIFE运行之前数据可用),选择不同的设计模式(例如使用传统构造函数),或者使用创建构造函数(您可以稍后调用)而不是对象的IIFE。


例如,这里有一个IIFE,它创建了一个构造函数:

var OrderNotifier = (function()
{
    //  private stuff would go here
    //  shared by all instances

    return function(/* constructor args go here */) {
        // per-instance private vars here
        return {
            notifyApproved: function(orderId, notifier, recipient)
            { 
                // use the notifier object passed as ctor param to send notifications 
                // related to orderId to recipients 
            },
            notifySomeOtherEvent: function(orderId, notifier, recipient)
            {
                // use the ctor params again
            }
        };
    }
}}();
// sometime later in your code
var notifier = new OrderNotifier(/* args here */);

您提供的两个选项本质上有两种不同的用途(而且,第一种方法最好与原型一起使用)。

原型对象创建

function OrderNotifier(orderId, notifier, recipients)
{
 this.orderId = orderId;
 this.notifier = notifier;
 this.recipients = recipients;
}
OrderNotifier.prototype.notifyApproved = function()
{ 
    // use the notifier object passed as ctor param to send notifications
    // in the form of this.notifier
    // related to orderId to recipients 
    // accessed through this.orderId and this.recipients
}
OrderNotifier.prototype.notifySomeOtherEvent = function() { 
    // use the ctor params again 
}

并使用

var on = new OrderNotifier(12345, new BasicNotifier(), someArrayOfEmails);
on.notifyApproved();

这种方法基本上是为了创建具有自己独特值但共享相同配置和原型(行为)的对象。使用IIFE(立即调用函数表达式)实际上是用于不同的操作。它可以用于保护全局命名空间免受变量污染。如果有一些工作需要做,但变量不应该一直存在,那么这就是IIFE的闪光点。此外,它们对于关闭值非常有用。然而,IIFE通常只运行一次就不存在了,因此它不需要实例化。如果要在函数中使用或关闭某些变量,则可以传入这些变量,但通常情况下,一旦执行,整个IIFE就会消失(尽管常见的模式是让它修改库的全局状态-jQuery会这样做)。


编辑

在你后期的编辑中,你为"私人物品会放在这里"创建了一个闭包,但这个例子太抽象了,无法真正突出任何好处。私人物品可以去那里,但实际上,它是静态的,可以简单地移动到notifyApproved或notifySometherEvent中。这确实是对IIFE的滥用,因为这可能只是

var orderNotifier = {
 notifyApproved: function(orderId,notifier,recipient){
  //store "private" information here
 },
 notifySomeOtherEvent : function(orderId,notifier,recipient){
  //store "private" information here
 }
};

您可以返回并在IIFE中进行编辑,以接受加载时传递的值,然后将其存储为"私有",但这样做的唯一好处是在脚本首次执行时关闭这些值。