2012-04-21 5 views
0

私は「makeExpression」の呼び出しに達したときに奇妙なJavaScript関数バインディング。この制御フローは正しいですか?

function PParser() { 
.... 
makeExpression = function (lexemes, index) { 

    return makeNumber(lexemes, index); 
} 

makeDeclaration = function(lexemes, index) 
{ 
    if (lexemes[index].TokenType != LALLPLexer.VAR) { 
     throw "Expected VAR at index " + index; 
    } 

    if (lexemes[index + 1].TokenType != LALLPLexer.ID) { 
     throw "Expected ID at index " + index + 1; 
    } 

    if (lexemes[index + 2].TokenType != LALLPLexer.ASSIGN) { 
     throw "Expected ASSIGN at index " + index + 2; 
    } 

    var expressionNodeResult = makeExpression(lexemes, index + 3); 

... 

、私はちょうど上で定義された関数に移動する制御フローを期待していた(A.jsそれを呼び出す)、同じ.jsファイルに次の関数定義を持っています。しかし、代わりに、 "makeExpression"という別の関数が完全に異なる.jsファイル(B.js)で呼び出されます。

function Controller() 
{ 
... 

this.parseToStatement = function(statementText) 
{ 
    makeExpression = function(expressionNode) 
    { 
     return new IntLiteral(expressionNode.Content); 
    } 

    try { 
     statement = parser.parseStatement(new LALLPLexer().lex(statementText)); 

     if (statement.NodeType == LALLPParser.DECLARATION) { 

      return new Declaration(statement.Id, makeExpression(statement.Expression)); 
     } 
    } 
    catch (exception) { 
     statement = new UnknownStatement(statementText); 
    } 

    return statement; 
} 
} 

私はなぜそれがわかりません。興味深いことに、上記の "parseStatement"という行は、 "makeExpression"呼び出しからの呼び出しチェーンの上にあります。これは正しいjavascriptの動作ですか、もしそうなら、なぜこの動作が期待されるのですか?意図した動作をどうやって得ることができますか?

+0

この動作は、通常、HTMLファイルにスクリプトを含める順序の結果です。その順序を変えて何が起こるかを見てみてください。 –

+0

@Elliotこれらの関数がクラス内で定義されていることを示すために、もう少しコンテキストを追加しました。インクルード注文はまだ関連していますか? – Dejas

+0

はい。 BがAの後に含まれる場合、最初の関数はオーバーライドされます。関数はグローバル変数として扱われるので、同じ関数を2回宣言すると関数がオーバーライドされるからです。あなたが 'makeExpression'関数を2回目に宣言したときに、ファイルAで宣言したクラスを修正しようとしています。 –

答えて

0

私はこれについて完全にはわかりませんが、jsは標準で変数をローカルに作成しないので、これらの関数はすべてグローバルに(つまりwindow変数に)アタッチされる可能性があり、したがって互いに上書きする可能性があります。

これらの定義にすべてvarを追加してください(または適切な場合はthis.)。多分それが助けになるでしょう。

+0

はい、ローカルで定義されていない関数(ある種のスコープ内)は 'window'変数に結び付けられます。つまり、関数を2回定義すると、2番目の宣言が最初の宣言を上書きします。スコープの外で 'var'を使って関数を定義すると、同じ振る舞いになります。 –

+0

私はそれを正しく思い出しました:-)ありがとう。 – Armatus

+0

そうです、それはいいですよ。コンストラクタのスコープで定義されたときにvarが必要であることを認識していませんでした。 – Dejas

関連する問題