我可以获得有关JavaScript代表的一些建议吗?

Cᴏʀ*_*ᴏʀʏ 6 javascript asp.net jquery delegates closures

我对JavaScript中的代理和闭包感到厌烦,并且认为我遇到过我想尝试使用其中一个或两个的情况.

我有一个Web应用程序,其行为很像表单应用程序,字段命中服务器以更改每个onBlur或onChange上的数据(取决于表单元素).我使用ASP.NET 3.5的Web服务和jQuery来完成大部分工作.

您需要了解的示例:

  • isBlocking() 是一种形成一些同步函数的简单机制(如互斥体)
  • isDirty(el) 检查以确保在浪费对服务器的调用之前实际更改了元素的值
  • Agent() 返回WebService代理类的单例实例
  • getApplicationState()将base-64编码的字符串传递给Web服务.此字符串表示应用程序的状态 - 元素的值和状态将传递给执行某些计算的服务.Web服务调用的onSuccess函数返回新状态,客户端处理并更新整个屏幕.
  • waitForCallback()设置一个isBlocking()检查互斥锁的标志

以下是大约50个非常相似的函数之一的示例:

function Field1_Changed(el) {
    if (isBlocking()) return false;
    if (isDirty(el)) {
        Agent().Field1_Changed($j(el).val(), getApplicationState());
        waitForCallback();
    }
}
Run Code Online (Sandbox Code Playgroud)

最大的问题是Agent().Field_X_Changed方法可以接受不同数量的参数,但通常只是值和状态.因此,编写这些函数会变得重复.到目前为止,我已经完成了尝试使用委托:

function Field_Changed(el, updateFunction, checkForDirty) {
    if (isBlocking()) return false;
    var isDirty = true; // assume true
    if (checkForDirty === true) {
        isDirty = IsDirty(el);
    }
    if (isDirty) {
        updateFunction(el);
        waitForCallback();
    }
}

function Field1_Changed(el) {
    Field_Changed(el, function(el) { 
        Agent().Field1_Changed($j(el).val(), getTransactionState()); 
    }, true);
}
Run Code Online (Sandbox Code Playgroud)

这没关系,但有时我可以有很多参数:

    ...
    Agent().Field2_Changed($j(el).val(), index, count, getApplicationState());
    ....
Run Code Online (Sandbox Code Playgroud)

我最终想要做的是做一个亚麻布电话,这样的事情(注意没有getTransactionState()电话 - 我希望以某种方式自动化):

// Typical case: 1 value parameter
function Field1_Changed(el) {
    Field_Changed(el, delegate(Agent().Field1_Changed, $j(el).val()), true);
}

// Rare case: multiple value parameters
function Field2_Changed(el, index, count) {
    Field_Changed(el, delegate(Agent().Field1_Changed, $j(el).val(), index, count), true);
}

function Field_Changed(el, theDelegate, checkIsDirty) {
    ???
}

function delegate(method) {
    /* create the change delegate */
    ???
}
Run Code Online (Sandbox Code Playgroud)

好的,我的第一个问题是:这一切都值得吗?这是难以阅读但更容易维护或反过来?这是一个非常好的事业,所以我最终可能会给这个奖励,但我很感激您提供的任何帮助.谢谢!

UPDATE

所以,我已经接受了一个答案,因为它指出了我正确的方向.我以为我会回来发布我的解决方案,以便其他可能刚开始与代表一起开始模拟的人.我也发布它,看看是否有人想尝试优化它或提出建议.这是Field_Changed()我提出的常用方法,checkForDirty并且omitState是可选参数:

function Field_Changed(el, args, delegate, checkForDirty, omitState) {
    if (isBlocking()) return false;
    if (!$j.isArray(args) || args.length == 0) {
        alert('The "args" parameter in Field_Changed() must be an array.');
        return false;
    }
    checkForDirty = checkForDirty || true; // assume true if not passed
    var isDirty = true; // assume true for updates that don't require this check
    if (checkForDirty === true) {
        isDirty = fieldIsDirty(el);
    }
    if (isDirty) {
        omitState = omitState || false; // assume false if not passed
        if (!omitState) {
            var state = getTransactionState();
            args.push(state);
        }
        delegate.apply(this, args);
        waitForCallback();
    }
}
Run Code Online (Sandbox Code Playgroud)

它处理我需要它的所有内容(检查脏,在需要时应用应用程序状态,并强制同步webservice调用.我使用它像这样:

function TransactionAmount_Changed(el) {
    Field_Changed(el, [cleanDigits($j(el).val())], Agent().TransactionAmount_Changed, true);
}
Run Code Online (Sandbox Code Playgroud)

cleanDigits 剥离用户可能试图输入的垃圾字符.所以,感谢大家,并且编码愉快!

Che*_*try 5

好的,很少的东西:

  1. 代理在javascript中非常简单,因为函数是一等成员.
  2. Function.apply 允许您使用参数数组调用函数.

所以你可以这样写

function Field_Changed(delegate, args)
{
    if (isBlocking()) return false;
    if (isDirty(args[0])) { //args[0] is el
        delegate.apply(this, args);
        waitForCallback();
    }
}
Run Code Online (Sandbox Code Playgroud)

称之为:

Field_Changed(Agent().Field2_Changed, [el, getApplicationState(), whatever...]);
Run Code Online (Sandbox Code Playgroud)