0

我编辑了这个问题,所以它会更有意义。
我有一个需要几个参数的函数——我们称之为它fc()。我将该函数作为参数传递给其他函数(让我们调用它们fa()fb())。通过的每个函数都fc()fc(). 如何传递fc()给每个函数而不必分别传递fc()'s 参数?下面是我希望它如何工作。

function fa(fc){
   fc.myvar=something
   fb(fc)
}

function fb(fc){
   fc.myothervar=something
   fc()
}

function fc(){
   doessomething with myvar and myothervar
}

下面是我现在的做法。当我添加参数时,它变得令人困惑,因为我还必须将它们添加到前面的函数中。 fb()fc()在其他地方使用,我失去了一些灵活性。

function fa(fc){
   myvar=something
   fb(fc,myvar)
}

function fb(fc,myvar){
   myothervar=something
   fc(myvar,myothervar)
}

function fc(myvar,myothervar){
   doessomething with myvar and myothervar
}

谢谢你的帮助


编辑 3 - 代码

我使用 JimmyP 的解决方案更新了我的代码。我会对 Jason Bunting 的非黑客解决方案感兴趣。请记住,这些函数中的每一个也可以从其他函数和事件中调用。

从 HTML 页面

<input type="text" class="right" dynamicSelect="../selectLists/otherchargetype.aspx,null,calcSalesTax"/>

加载部分时设置事件处理程序

function setDynamicSelectElements(oSet) {
    /**************************************************************************************
    * Sets the event handlers for inputs with dynamic selects
    **************************************************************************************/
    if (oSet.dynamicSelect) {
        var ySelectArgs = oSet.dynamicSelect.split(',');
        with (oSet) {
            onkeyup = function() { findListItem(this); };
            onclick = function() { selectList(ySelectArgs[0], ySelectArgs[1], ySelectArgs[2]) }
        }
    }
}

onclick事件构建列表

function selectList(sListName, sQuery, fnFollowing) {
    /**************************************************************************************
    * Build a dynamic select list and set each of the events for the table elements
    **************************************************************************************/
    if (fnFollowing) {
        fnFollowing = eval(fnFollowing)//sent text function name, eval to a function
        configureSelectList.clickEvent = fnFollowing
    }
    var oDiv = setDiv(sListName, sQuery, 'dynamicSelect', configureSelectList); //create the div in the right place
    var oSelected = event.srcElement;
    if (oSelected.value) findListItem(oSelected)//highlight the selected item
}

创建列表

function setDiv(sPageName, sQuery, sClassName, fnBeforeAppend) {
    /**************************************************************************************
    * Creates a div and places a page in it.
    **************************************************************************************/
    var oSelected = event.srcElement;
    var sCursor = oSelected.style.cursor; //remember this for later
    var coords = getElementCoords(oSelected);
    var iBorder = makeNumeric(getStyle(oSelected, 'border-width'))
    var oParent = oSelected.parentNode

    if (!oParent.id) oParent.id = sAutoGenIdPrefix + randomNumber()//create an ID
    var oDiv = document.getElementById(oParent.id + sWindowIdSuffix)//see if the div already exists
    if (!oDiv) {//if not create it and set an id we can use to find it later
        oDiv = document.createElement('DIV')
        oDiv.id = oParent.id + sWindowIdSuffix//give the child an id so we can reference it later    
        oSelected.style.cursor = 'wait'//until the thing is loaded
        oDiv.className = sClassName
        oDiv.style.pixelLeft = coords.x + (iBorder * 2)
        oDiv.style.pixelTop = (coords.y + coords.h + (iBorder * 2))
        XmlHttpPage(sPageName, oDiv, sQuery)
        if (fnBeforeAppend) {
            fnBeforeAppend(oDiv)
        }
        oParent.appendChild(oDiv)
        oSelected.style.cursor = ''//until the thing is loaded//once it's loaded, set the cursor back
        oDiv.style.cursor = ''
    }
    return oDiv;
}

定位和调整列表大小

function configureSelectList(oDiv, fnOnClick) {
    /**************************************************************************************
    * Build a dynamic select list and set each of the events for the table elements
    * Created in one place and moved to another so that sizing based on the cell width can
    * occur without being affected by stylesheet cascades
    **************************************************************************************/
    if(!fnOnClick) fnOnClick=configureSelectList.clickEvent
    if (!oDiv) oDiv = configureSelectList.Container;
    var oTable = getDecendant('TABLE', oDiv)
    document.getElementsByTagName('TABLE')[0].rows[0].cells[0].appendChild(oDiv)//append to the doc so we are style free, then move it later
    if (oTable) {
        for (iRow = 0; iRow < oTable.rows.length; iRow++) {
            var oRow = oTable.rows[iRow]
            oRow.onmouseover = function() { highlightSelection(this) };
            oRow.onmouseout = function() { highlightSelection(this) };
            oRow.style.cursor = 'hand';
            oRow.onclick = function() { closeSelectList(0); fnOnClick ? fnOnClick() : null };
            oRow.cells[0].style.whiteSpace = 'nowrap'
        }
    } else {
        //show some kind of error
    }
    oDiv.style.width = (oTable.offsetWidth + 20) + "px"; //no horiz scroll bars please
    oTable.mouseout = function() { closeSelectList(500) };
    if (oDiv.firstChild.offsetHeight < oDiv.offsetHeight) oDiv.style.height = oDiv.firstChild.offsetHeight//make sure the list is not too big for a few of items
}
4

4 回答 4

2

好的,所以 - 从哪里开始?:) 这是开始的部分函数,​​您将需要它(现在和将来,如果您花费大量时间破解 JavaScript):

function partial(func /*, 0..n args */) {
  var args = Array.prototype.slice.call(arguments, 1);
  return function() {
    var allArguments = args.concat(Array.prototype.slice.call(arguments));
    return func.apply(this, allArguments);
  };
}

我看到很多关于您的代码的事情让我感到畏缩,但是由于我没有时间真正批评它,而且您没有要求它,如果您想摆脱黑客攻击,我会建议以下内容您当前正在使用,以及其他一些东西:

setDynamicSelectElements() 函数

在此函数中,您可以更改此行:

onclick = function() { selectList(ySelectArgs[0], ySelectArgs[1], ySelectArgs[2]) }

对此:

onclick = function() { selectList.apply(null, ySelectArgs); }

selectList() 函数

在这个函数中,你可以在你使用 eval 的地方去掉这段代码——除非你有充分的理由这样做,否则不要使用 eval,这是非常危险的(去阅读它):

if (fnFollowing) {
   fnFollowing = eval(fnFollowing)
   configureSelectList.clickEvent = fnFollowing
}

并改用它:

if(fnFollowing) {
   fnFollowing = window[fnFollowing]; //this will find the function in the global scope
}

然后,更改此行:

var oDiv = setDiv(sListName, sQuery, 'dynamicSelect', configureSelectList);

对此:

var oDiv = setDiv(sListName, sQuery, 'dynamicSelect', partial(configureSelectListAlternate, fnFollowing));

现在,在我提供的代码中,我有“configureSelectListAlternate”——这是一个与“configureSelectList”相同但参数顺序相反的函数——如果您可以将参数的顺序反转为“configureSelectList”,这样做,否则这是我的版本:

function configureSelectListAlternate(fnOnClick, oDiv) {
   configureSelectList(oDiv, fnOnClick);
}

configureSelectList() 函数

在此函数中,您可以消除此行:

if(!fnOnClick) fnOnClick=configureSelectList.clickEvent

这不再需要了。现在,我看到了一些我不明白的东西:

if (!oDiv) oDiv = configureSelectList.Container;

我没有看到您在任何其他代码中挂钩该 Container 属性。除非你需要这条线,否则你应该可以摆脱它。

setDiv() 函数可以保持不变。


不太令人兴奋,但你明白了——你的代码真的可以使用一些清理——你是否有充分的理由避免使用像 jQuery 或MochiKit这样的库?它会让你的生活更轻松......

于 2009-05-02T04:00:42.287 回答
1

函数的属性不能作为局部范围内的变量使用。您必须将它们作为属性访问。因此,在“fc”中,您可以通过以下两种方式之一访问“myvar”:

// #1
arguments.callee.myvar;
// #2
fc.myvar;

哪个都好...

于 2009-05-01T19:40:31.680 回答
0

也许您正在寻找Partial Function Application,或者可能是currying?

这是一篇关于差异的博客文章的引述:

在部分应用程序接受一个函数并从中构建一个接受较少参数的函数的情况下,currying 通过组合每个接受一个参数的函数来构建接受多个参数的函数。

如果可能的话,如果您可以简化示例和/或提供实际的 JS 代码而不是伪代码,这将对我们有所帮助。

于 2009-05-01T19:36:45.900 回答
0

尝试继承 - 通过将任何对象作为参数传递,您可以访问内部的任何变量,例如:

function Obj (iString) { // Base object
    this.string = iString;
}
var myObj = new Obj ("text");

function InheritedObj (objInstance) { // Object with Obj vars
    this.subObj = objInstance;
}
var myInheritedObj = new InheritedObj (myObj);

var myVar = myInheritedObj.subObj.string;
document.write (myVar);

subObj 将采用 myObj 的形式,因此您可以访问其中的变量。

于 2009-05-01T23:19:19.327 回答