Javascript函数对象

时间:2009-05-01 19:15:55

标签: javascript dhtml

我编辑了这个问题,因此更有意义 我有一个需要几个参数的函数 - 让我们称之为fc()。我通过其他函数将该函数作为参数传递(让我们称之为fa()fb())。 fc()经过的每个函数都会向fc()添加一个参数。如何将fc()传递给每个函数而不必单独传递fc()的参数?以下是我希望它的工作方式。

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 个答案:

答案 0 :(得分: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这样的库?它会让你的生活更轻松......

答案 1 :(得分:1)

函数的属性不可用作本地范围中的变量。您必须将它们作为属性访问。因此,在'fc'中你可以通过以下两种方式之一访问'myvar':

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

要么好......

答案 2 :(得分:0)

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

以下是a blog post on the difference的引用:

  

当部分应用程序接受一个函数并从中构建一个函数,该函数接受较少的参数,currying构建函数,这些函数通过函数组合获取多个参数,每个参数都采用一个参数。

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

答案 3 :(得分: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的形式,因此您可以访问其中的变量。