3

関数にスコープがある場合、そのスコープ内で実行する必要がありますが、ここでは異なると思います。コードを参照してください

  function foo() {
    var privateVal = "Private Val";
    this.publicVal = "Public Val";

    var privateAlert = function (str) {
      alert(str + this.publicVal);
      alert(str + privateVal);
    }

    this.Run = function () //see here
    {
      privateAlert("Private Call: ");

      this.publicAlert = privateAlert;
      this.publicAlert("Public Call: ");

      privateAlert = this.publicAlert;
      privateAlert("Private Call: ");
      this.publicAlert("Public Call: ");
    }
  }

  var bar = new foo();
  bar.Run();

新しいオブジェクトが作成されると、run() はオブジェクトのプライベート メソッドになるか、var bar にのみ属するメソッドになります。宣言された関数内からのみ実行できますが、現在他のオブジェクトに属しているメソッドからは実行できません。このplzを明確にしてください。

4

3 に答える 3

3

重要なのは、関数がインスタンス化される場所です。この場合、「Run」は「foo」コンストラクター内でインスタンス化され、そのコンテキストではプライベート メソッドが確実に表示されます。つまり、「Run」関数の周りのクロージャーの一部になります。

次のように考えてください。「Run」関数のコードは、「foo」コンストラクター内に表示されます。「実行」のコードは、「foo」内のすべてのローカル変数を「見る」ことができ、「foo」がさらに別の関数内にある場合、それらの変数もすべて見ることができます。定義は「foo」が呼び出されたときにのみ有効になるため、後で呼び出されたときはいつでも、「Run」内のコードでこれらすべてのローカル変数を常に使用できます。それが「閉鎖」という言葉の意味です。

JavaScript でのスコープと可視性は、Java、C++、C# などのクラスを含むより静的な言語での動作とは大きく異なります。これらの言語では、オブジェクトを明示的に構築してから、それらのオブジェクト参照を介して関数の呼び出しを開始します。JavaScript では、クロージャーは、関数呼び出しから「エスケープ」する関数を暗黙的にラップする自動オンザフライ オブジェクトのようなものです。これらのオブジェクトに直接アクセスすることはできませんが、それにもかかわらず、それらは本物です。

于 2013-01-03T16:09:39.240 に答える
0

ラファエレはすでにあなたの質問のほとんどに答えていると思います。しかし、便宜上、別の方法で表現し、従うべきコードをいくつか追加してみましょう。

コードがそのように動作する理由を理解するために、ここで学ぶことができることが 2 つあります。

  1. JavaScript には の遅延バインディングがありthisます。メソッドを呼び出す場合にのみ、ランタイムは呼び出されるオブジェクトを「オン」に決定します。デフォルトはグローバル オブジェクトです (例:windowブラウザ、globalnode.js など)。thisグローバル以外のものを取得するには、 を介して行ったように、目的のオブジェクトのプロパティとして関数を割り当てる必要がありthis.publicAlert = privateAlert;ます。その後、同じ関数であっても、privateAlert()( global で) 直接this呼び出すか、 this を介してローカルで呼び出すかによって違いが生じます。this.publicAlert()

  2. すでに他の回答で指摘されているように。Javascript には 、 などはありませんpublicprivateスマート スコープを使用して行ったように、プライベート変数を「モデル化」する必要があります。あなたの例でprivateValは、誰も外部から読み書きできないという意味でプライベートです。についても同様ですprivateAlertFooコンストラクターとメソッドのステートメントを介してのみ、runそれらにアクセスできます。

何が起こっているかを示すためにあなたの例を拡張しました(ps:console.log通常、使用するよりも使用する方がはるかに賢明ですalert):

function Foo() {
    var privateVal = "Private Val";
    var that = this;
    this.publicVal = "Public Val";

    var privateAlert = function (str) {
        console.log("---" + str + "---")
        console.log("isLocalThis? ", this == that)
        console.log("isGlobalThis?", this == globalThis)
        console.log("private:     ", privateVal)
        console.log("public:      ", this.publicVal || "publicVal not available on 'this'")
    }

    this.run = function () {
        console.log("scope of run:", that, bar, privateAlert)
        console.log("isLocalThis? ", this == that)
        console.log("isGlobalThis?", this == globalThis)

        privateAlert("Private Call: ");

        this.publicAlert = privateAlert;
        this.publicAlert("Public Call: ");

        privateAlert = this.publicAlert;
        privateAlert("Private Call: ");
        this.publicAlert("Public Call: ");
    }
}

var bar = new Foo();
bar.run();

ところで:consolealertグローバルのプロパティthis(つまり、window)。

于 2013-01-03T18:18:51.553 に答える
0

スコープはネーム システムに関するものであり、アクセス権については何も述べていません。たとえば、Java には、アクセス修飾子として知られる 3 つのキーワードあります。Javascript はアクセス修飾子を定義していないため、すべての名前は public です。publicprivateprotected

このように言いましょう: ファイルシステムからファイルを読み取るには、次の 2 つが必要です。

  1. まずはファイル名。OS にファイル ポインタを提供するように要求すると、おそらく相対ファイル名と現在のディレクトリから絶対パス名を作成した後、最初にファイル名が存在するかどうかがチェックされ、次にファイルが存在する場合にのみチェックされます。
  2. ストリームから読み取る権利があるかどうかを確認し、最終的にストリームへのハンドラーを提供します。

Javascriptスコープは、名前が現在のコンテキストで何かを意味するかどうかを判断するためのルールです。名前に意味がある場合は、いつでもアクセスできます。Javascript は非パブリック修飾子を定義していないためです。

あなたの場合、アクセスを要求しますbar.Run。Javascript インタープリターは、現在のコンテキスト (グローバル オブジェクトであると想定) を使用して、「javascript ファイルシステム」に「呼び出された」オブジェクトを要求します.bar.Run(最初のドットは意図的なもので、ルートを示します)。名前が見つかったら、それが存在することを意味し、いつでもアクセスできます (この場合は関数を呼び出します)。ところで、javascript ファイルシステムのようなものはありません。専門用語を使用せず、直感的なアナロジーを使用してアイデアを伝えるだけです。

同様に、スコープ ルールがチェックされ、コード全体で名前が解決されます。内部this.Runでは、名前を解決privateAlertできます。これが重要な唯一のルールです。グローバルは を参照でき、グローバルはアクセスでき、それに割り当てられた機能は にアクセスできます。これがチェーンですbarbar.RunprivateAlert

于 2013-01-03T16:27:53.943 に答える