10

コードは次のようになります (構文は奇妙に見えるかもしれませんが、私の知る限り、何も問題はありません。それとも何かありますか?)

var add=function addNums(a, b) {                     
   return a+b;
 }                     
 alert("add: "+ add(2,3));           // produces 5
 alert("addNums: "+addNums(2,3));        // should also produce 5

addNums()関数として宣言されています。そのため、パラメーターを渡すと、結果も返されるはずです。

次に、2 番目のアラート ボックスが表示されないのはなぜですか?

4

9 に答える 9

23

名前付き関数式 (NFE)が表示されます。

無名関数式は、名前のない関数を変数1に割り当てる場所です。

var add = function () {
  console.log("I have no own name.");
}

名前付き関数式は、名前付き関数を変数に代入する場所です (驚き!):

var add = function addNums() {
  console.log("My name is addNums, but only I will know.");
}

関数の名前は、関数内でのみ使用できます。これにより、関数の「外部名」を必ずしも知らなくても、再帰を使用できます-最初に設定する必要がなくても(コールバック関数を考えてください)。

選択した名前は既存の名前を隠します。そのため、別の名前が別の場所addNumsで定義されていても、上書きされません。これは、スコープの問題や何かを壊すことを恐れずに、好きな名前を使用できることを意味します。

以前はarguments.callee、名前を知らなくても関数自体を参照していました。しかし、そのサポートは JavaScript 2から削除されているため、現在これを行うには NFE が正しい方法です。

このトピックについて読むべき多くの資料があります: http://kangax.github.io/nfe/


1変数に代入する必要はありません。単純な関数宣言と区別するための例としてのみ使用します。JS が式 (たとえば、関数の引数) を期待する他のコンテキストである可能性があります。

2厳格モードが有効な状態で を使用しようとすると、エラーが発生しますarguments.callee

于 2013-05-19T05:39:54.540 に答える
5

問題

名前付き関数式を使用しています- 関数式の名前はその関数のスコープ外では使用できません:

// Function statement
function statement() {
    console.log("statement is a type of " + typeof statement);
}
statement();
console.log("statement is a type of " + typeof statement);

結果:

statement is a type of function
statement is a type of function

一方:

// Function expression with a name
var expression = function namedExpression() {
    console.log("namedExpression is a type of " + typeof namedExpression);
};

expression();
// namedExpression();  // uncommenting this will cause an exception
console.log("expression is a type of " + typeof expression);
console.log("namedExpression is a type of " + typeof namedExpression);

生成されます:

namedExpression is a type of function
expression is a type of function
namedExpression is a type of undefined

ソリューション

何をしようとしているかに応じて、次のいずれかを実行します。

  • ステートメントを使用するように関数宣言を変更してから、関数にエイリアスを設定します。

    function addNums(a, b) {
        return a + b;
    }
    
    var add = addNums;
    
  • 両方の名前を式にエイリアスします。

    var add = addNums = function addNums(a, b) {
        return a + b;
    };
    

なぜ JavaScript はこのように動作するのでしょうか?

名前付き関数式は、それ自体の内部で関数を参照でき、デバッガーで参照する名前を与えるので便利です。ただし、関数を値として使用する場合、通常、関数の一部が外側のスコープに漏れることは望ましくありません。検討:

(function setup() {
    var config = retrieveInPageConfig();
    if (config.someSetting) {
        performSomeOtherSetup();
    }
    kickOffApplication();
})();

これは関数式の完全に正当な使用法です。このような場合、名前が外側のsetupスコープに漏れることは期待できません。名前付き関数式を変数に代入することは、これの特殊なケースであり、たまたま関数ステートメントの宣言のように見えます。

于 2013-05-19T05:37:15.083 に答える
4

addNums、新しく定義された関数のスコープでのみ使用できます

明らかに、関数式に名前 (技術的には — 識別子) がある場合、名前付き関数式と呼ばれます。最初の例で見たもの — var bar = function foo(){}; — まさにそれでした — foo が関数名である名前付き関数式。覚えておくべき重要な詳細は、この名前は 新しく定義された関数のスコープでのみ使用できるということです。仕様では、識別子を外側のスコープで使用できないようにする必要があります。

この記事の詳細をお読みください。

于 2013-05-19T05:34:52.657 に答える
1

テスト Web アプリにコードを追加しましたが、問題なく動作します。これがコードです。コード/アプリの詳細を教えてください。

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="JavascriptTest.aspx.cs" Inherits="GetGridViewColumnValue.JavascriptTest" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>

    <script type="text/javascript">
        var add = function addNums(a, b) {
            return a + b;
        }
        alert("add: " + add(2, 3));           // produces 5
        alert("addNums: " + addNums(2, 3));

     </script>

</head>
<body>
    <form id="form1" runat="server">
    <div>

    </div>
    </form>
</body>
</html>

乾杯!!!

于 2013-05-19T05:42:02.093 に答える
1

次のコードを検討してください。

var f = function g() {
    // function
};

g関数自体でのみアクセスでき、再帰関数を記述するために関数を単独で使用する場合に必要です。たとえば、次のfactorial関数が必要です。

var f = function factorial(x) {
    if (x <= 1) return 1;

    // here we want to use the function itself
    return x * factorial(x - 1);
};

console.log(f(5));

ただし、次の方法で関数自体にアクセスできるため、本当に必要ですarguments.callee

// note that the function has not any name
var f = function (x) {
    if (x <= 1) return 1;

    // here we want to use the function itself
    return x * arguments.callee(x - 1);
};

console.log(f(5));
于 2013-05-19T05:47:02.607 に答える
1

名前付き関数として宣言する必要があります。

function addNums(){

}

または関数を変数に割り当てます。

var add= function(){// your code }

addNum() が何も返さない理由は、宣言した方法でグローバルスコープに追加されていないためです。

于 2013-05-19T05:29:47.127 に答える
1

コードを少し変更しました:

var add = function addNums(a, b){
             return a+b;
}
console.log(add);
console.log(typeof(add));
console.log("add: "+ add(2,3));           // produces 5
console.log("addNums: "+addNums(2,3));

次に、node.js 内で実行して、次の出力を取得します。

[Function: addNums]
function
add: 5

/home/mel/l.js:44
console.log("addNums: "+addNums(2,3));
                        ^
ReferenceError: addNums is not defined (... backtrace)

通常、インライン匿名メソッドが割り当てられた変数は、 Here で[Function]呼び出されると出力され、関数の名前も出力されます。console.log(var);console.log(add);

したがって、 addNums 宣言が無効または使用されていないようではなく、変数 add にバインドされるようにスコープが設定されているだけです。

于 2013-05-19T05:57:13.593 に答える
1

デモ

function addNums(a, b) {
   return a+b;
}
var add = addNums;
alert("add: "+ add(2,3));
alert("addNums: "+addNums(2,3));
于 2013-05-19T05:34:06.560 に答える
0

addNums はグローバル名前空間の関数ではありません.代入演算子内でのみ定義される関数です..

アクセスしたい場合は、次のことを試してください。

  function addNums(a, b) 
  {                     
     return a+b;
  } 

  var add = addNums;


  var add = function <---- the function name is add and it's value is a function..            
于 2013-05-19T05:27:05.173 に答える