0

私はそれがより意味をなすように質問を編集しました。
いくつかの引数が必要な関数があります-それを呼び出しましょう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のソリューションを使用してコードを更新しました。JasonBuntingの非ハックソリューションに興味があります。これらの各関数は、他の関数やイベントからも呼び出されることに注意してください。

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」内では、次の 2 つの方法のいずれかで「myvar」にアクセスできます。

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

どちらでもいい...

于 2009-05-01T19:40:31.680 に答える
0

Partial Function Applicationやカリー化を探しているのではないでしょうか?

違いに関するブログ投稿からの引用を次に示します。

部分適用が関数を取り、そこからより少ない引数を取る関数を構築するのに対し、カリー化は、それぞれが単一の引数を取る関数の合成によって、複数の引数を取る関数を構築します。

可能であれば、例を単純化したり、疑似コードの代わりに実際の 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 に答える