0

JS の初心者です。最近、よく知らない構文を使用するコードをいくつか調べました。これが私の質問に続く例です:

function Group(args) {
  this.showItem = showItem;
  function showItem(args) {
    ...
  }
}
var group = new Group (args);

質問:

  1. 私が理解しているように、作成function Groupしてからインスタンス化group = new Groupすることは、クラスを定義してからそのクラスのオブジェクトをインスタンス化することと本質的にプロトタイプに相当します。あれは正しいですか?

  2. のプロパティ (メソッド?) についてGroup、上記の構文でshowItem呼び出されるのは何ですか? 次のように定義してみませんか。

    this.showItem = function(args){...};
    

    コードを上記のように変更すると、別の動作が変更されますか?

  3. 上記のように定義した場合、その構文は何と呼ばれますか?

4

2 に答える 2

3
  1. Group関数はコンストラクターとして使用されています。あなたの直感は基本的に正しいです。

  2. ローカル変数を再利用したい場合を除き、 のような無名関数式を使用しない正当な理由はありません。this.showItem = function(args){...};showItem

  3. どの構文を意味するのかわかりません。はfunction(args){...}無名関数式であり、this.showItemは object のメンバーを参照していますthis。まとめると、「オブジェクトのメンバー関数を設定する」と言えるのではないでしょうか。

showItemおまけのヒント (すでにご存知でしょうか?):定義の前に使用できる理由は、関数ホイストによるものです。

編集:

関数式と関数宣言、および名前付き関数と無名関数について質問しているようです。主な違いは次のとおりです。

  • 関数宣言は常に独立しています。それらは、割り当てなどの別の操作の一部になることはありません。最初の例では、関数宣言を使用していますfunction showItem(args) {...}。関数は、何らかの操作 (代入、引数として渡されるなど) で式として使用されます。2 番目のケースでは、関数式を使用します。

  • 関数宣言は現在の関数スコープの先頭に引き上げられるためshowItem、最初のケースでは が定義され、代入操作で使用するときに関数が含まれます。関数式は巻き上げられません。

  • 関数宣言には常に名前が付けられます。関数式は、名前付きまたは匿名の場合があります。関数が名前で定義されている場合、その名前はname関数オブジェクトのプロパティとしてアクセスできます。関数の名前は不変であり、関数への参照を保持する変数から独立しています。また、関数本体内のコードは、ローカル変数としてその名前で関数を参照できます (これは、名前付き関数式内の再帰に役立つ場合があります)。

レビューする:

  • 関数定義:function showItems(args){...};
  • 無名関数式:this.showItems = function(args){...};
  • 名前付き関数式:this.showItems = function showItemsName(args){...};

最初のケースでは、 defined というローカル変数がshowItemsあり、 の定義がshowItems一番上に持ち上げられています。後者の 2 つのケースの違いは、3 番目のケースと 2 番目のケースではthis.showItems.name" " になることです。また、関数オブジェクトへの参照を保持する 3 番目の関数の関数本体内のローカル変数になります。showItemsNameundefinedshowItemsName

于 2012-12-31T17:36:58.803 に答える
2
  1. Group関数はコンストラクタとして使用されます。ただし、これを行う方法は少し非効率的です。このコードが行っていることは、新しい関数を作成し、構築されたオブジェクトにアタッチすることです。彼はクロージャーを作成したい (つまり、コンストラクターの名前空間にのみ存在する変数を使用する) ためにこれを行っている可能性がありますが、その理由がない場合は、これを行う方が適切です。

    function Group(args){}
    Group.prototype.showItem = function(args) {};
    

    このようにして、プロトタイプチェーンを介してshowItem構築されたすべてのオブジェクト間で同じ関数が共有されます。Group

  2. 元のコードと無名関数を使用する利点は、関数に名前があることです。無名関数呼び出しでいっぱいのトレースバックを読むのは面白くないので、これはデバッグに非常に役立ちます! 展開すると、キーワードを使用するものには次の 3 つのタイプがfunctionあります。

    • 関数の宣言プログラムまたは関数 (つまり、独自の名前空間を作成する/持つもの) のトップ レベルでは、名前を付けて関数を宣言できます。(名前はプログラム全体で関数オブジェクトに残り、トレースバックに表示されます。)これはfunction showItem(args) {}あなたの例です。(これは、ファイルまたは関数のトップレベルでの関数宣言にすぎないことに注意してください。最後に非常によく似たものがあります。) 慣例により、ほとんどの人はこれらの後のセミコロンを省略しているようです。
    • 関数式 式の一部 (代入、戻りなど) は、関数式です。関数式の識別子部分はオプションであるため、これらは両方とも関数式です。

      var myfunc1 = function(){};
      var myfunc2 = function MyFunctionName(){};
      

      2 番目の形式は「名前付き関数式」と呼ばれます。この形式を使用することの大きな利点はMyFunctionName、匿名関数ではなくなることです。この名前は関数に関連付けられ、トレースバックに表示されます (たとえば)。ただし、JScript (IE <= 8) には非常に深刻なバグがあり、これらを使用すると問題が発生します。詳細については、上でリンクした記事をお読みください。

    • 最後に、関数ステートメントと呼ばれる一般的な拡張構文があります。これらは、トップレベルではないことを除いて、関数宣言とまったく同じように見えます! 例えば:

      function() {
          function foo(){} // function declaration
          if (1) {
              function bar(){} // function STATEMENT--not standard JS!
          }
      }
      

      この拡張機能に依存するべきではありませんが、代わりにこれを行う必要があります。

      function() {
          var bar;
          if (1) {
              bar = function bar(){};
          }
      }
      
  3. this.showItem = function(){}「割り当ての関数式」と呼ばれ、元のコードは「関数宣言」を使用しているだけです。

于 2012-12-31T18:10:07.113 に答える