0

C / C ++、Javaでプログラムしたので、次のプログラムの出力を理解するのが難しいと感じています。

http://jsfiddle.net/iamrohitbanga/nubgw/

var foo = function() {}
foo.prototype.out = function() {
    console.log(this.num);
}
var bar = function() {};

var f = new foo();
f.num = 1;
var b = new bar();
b.num = 2;

console.log(this);           // 1
f.out();                     // 2
foo.prototype.out.call(b);   // 3
foo.prototype.out.call(bar); // 4

次の出力が表示されます

Window
1
2
undefined

私はしばらくの間javascriptでコーディングしていて、いくつかの概念を理解できますが、すべてが明確であるとは限りません。

私は大まかな理解を持っています。グローバル空間では、これはウィンドウを指しているので、出力の最初の行は明確です。2行目では、関数outがfで呼び出されているので、このinoutの値はfだと思います。3つ目は、入力をbとして関数を呼び出すことにより、-thisの値がbに設定されると感じています。4番目の1つのバーは、ディクショナリに「num」という名前のメンバーがないグローバルオブジェクトです。

私の理解は正しいですか?誰かがこのプログラムの文脈で「これ」と「プロトタイプ」の役割を説明できますか?プロトタイプの構文が少しわかりにくいと思います。また、GmailウィンドウでF12キーを押して、そこにプログラムを貼り付けると、Chromeで表示されます。出力の3行目は未定義で、2行ではありません。しかしjsfiddleでは2行です。少し不気味なようです。なぜ違うのですか?

4

3 に答える 3

2

console.log(this)

あなたの仮定は正しいです。プログラムは、ブラウザのグローバルスコープで実行されていwindowます。


f.out();

プロトタイプの概念は、C /C++またはJavaに存在するかどうかはわかりません。基本的に、オブジェクトのコンストラクターのプロトタイプは、オブジェクトが継承できるものです。のプロトタイプに関数を追加するfooと、のすべてのインスタンスで使用できるようになりますfoo

この場合、プログラムの前半で、というインスタンスを作成しましfoof。次に、fcalledのプロパティをに設定numします1

out、のプロトタイプのf拡張によって利用可能な関数は、コンテキストが呼び出されているオブジェクトのプロパティです(この場合は)。fooconsole.lognumf

したがって、をf.out();出力し1ます。


foo.prototype.out.call(b);

callFunctionオブジェクトのプロトタイプの関数です。call最初の引数のコンテキストで関数を呼び出します。基本的に、この行(foo.prototype.out.call(b);)は、コンテキスト引数として渡されるのb.out();と同じです。b

この行の出力の残りの説明は、最後の行の説明全体と同じです。


foo.prototype.out.call(bar);

この最後の行では、を呼び出しoutていbarます。barFunctionオブジェクトです。したがって、プロパティはbarありません。numbar.numundefined

barこれは、とで行ったのと同じ方法でプロパティを追加できないということではありませfb。関数もオブジェクトです。したがって、ととbarまったく同じ方法でプロパティを追加できます。追加すると、あなたが考えているものが正確に得られます。または、少なくとも私があなたが考えていることを願っています...fbbar.num = 3

于 2012-09-23T05:11:54.543 に答える
1

thisコードが実行されているスコープを表します。あなたの場合、それはグローバルスコープwindowです。

JavaScriptのプロトタイプは、プロパティとメソッドを持つ単なるオブジェクトです。メンバーを追加したり、継承したりすることもできます。詳細については、この記事を読むことができます。

コードを分解してみましょう。これを1つずつ確認してください。

  1. f.out();

    これも次のオブジェクトを参照します

    var f = new foo();
    f.num = 1; //Here you define a property `num` as 1
    

    次にf.out()、プロトタイプ関数を呼び出すと、単純にログに記録されますnum

  2. foo.prototype.out.call(b);

    ここでは、関数に直接アクセスして、オブジェクトを関数に渡します。したがって、メソッドが実行されると、thisは代わりに渡されるオブジェクトを表すため、その値をログに記録することになります。

  3. foo.prototype.out.call(bar);

    この部分では、オブジェクトバーは空のオブジェクトであるため、関数はそのプロパティをvar bar = function() {};読み取ることができないため、次のように出力されます。numundefined

于 2012-09-23T05:02:42.140 に答える
1

これは、現在のスコープを指します。

そうは言っても、段階的にこれがあなたが得ている結果を得ている理由です

var foo = function() {}
foo.prototype.out = function() {//f.out inherits this and so prints 1
    console.log(this.num);
}
var bar = function() {};

var f = new foo();
f.num = 1;
var b = new bar();
b.num = 2;

console.log(this);           
 /* At this point you are making the above log call, outside of any local scope.
 in the global scope =this= refers to =window= */

f.out();
 /* In here the keyword =this= refers to the object =f=
 If we look above it says f.num is 1, so the inherited function which outputs 
 the =num= property then outputs 1.*/


foo.prototype.out.call(b);
/*by adding the call method you are assigning the this keyword to the b object, and
since b.num is 2, just as in the previous step that is being output*/

foo.prototype.out.call(bar); // 4
/*This returns undefined because as in all previous steps, inside the =out= 
function we are printing object.num.  The bar object, however, does not have 
this value*/

コードにコメントとして説明を入れました。Gmailの奇妙な動作については、これらはすべてグローバルスコープにあるため、Gmailにすでに含まれているコードによって何かが上書きされている可能性があります。上記の発生を防ぐためのクロージャを次に示します。最初のログは変更されます。これはグローバルスコープを参照しなくなるためです。

(function(){

   var foo = function() {}
   foo.prototype.out = function() {
       console.log(this.num);
   }
   var bar = function() {};

   var f = new foo();
   f.num = 1;
   var b = new bar();
   b.num = 2;

   console.log(this);           // 1
   f.out();                     // 2
   foo.prototype.out.call(b);   // 3
   foo.prototype.out.call(bar); // 4

})();
于 2012-09-23T05:25:22.323 に答える