簡體   English   中英

了解此javascript代碼的輸出

[英]Understanding the output of this javascript code

用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編碼了一段時間了,可以理解一些概念,但是並不是所有事情對我來說都是清楚的。

我有一個大概的了解。 我覺得在全局空間中它指向窗口,因此輸出的第一行很清楚。 對於第二行,我認為由於函數out是在f上調用的,因此in in的值為f。 對於第三個,我的感覺是,通過使用input作為b調用函數,將-this的值設置為b。 對於第四個,一個小節是一個全局對象,它的字典中沒有名為“ num”的成員。

我的理解正確嗎? 有人可以在此程序的背景下解釋“ this”和“ prototype”的作用嗎? 我發現原型的語法有些晦澀。 在chrome窗口中,當我在gmail窗口中按F12鍵並將程序粘貼到其中時,也是如此。 輸出的第三行是未定義的,而不是2。但是在jsfiddle中,它是兩個。 這似乎有些令人毛骨悚然。 為什么不同?


console.log(this)

您的假設是正確的。 您的程序在瀏覽器中是window的全局范圍內運行。


f.out();

我不確定在C / C ++或Java中是否存在原型的概念。 本質上,對象構造函數的原型是對象可以繼承的東西。 添加到函數foo的原型使其可用於所有實例foo秒。

在這種情況下,在程序的前面,您創建了一個名為ffoo實例。 然后,將名為numf屬性設置為1

outf的擴展名foo的原型console.log提供的功能,此對象是要調用其上下文的對象的num屬性(在本例中為f )。

因此, f.out(); 打印1


foo.prototype.out.call(b);

callFunction對象原型上的一個函數。 call在第一個參數的上下文中調用一個函數。 本質上,這一行( foo.prototype.out.call(b); )與執行b.out();相同b.out(); 因為b作為上下文參數傳遞。

該行輸出的其余解釋與最后一行的解釋完全相同


foo.prototype.out.call(bar);

在最后一行,你調用outbar bar是一個Function對象。 bar沒有num屬性,因此bar.numundefined

這並不是說您不能像使用fb一樣添加屬性來bar顯示。 函數也是對象。 因此,您可以添加屬性以與對fb完全相同的方式進行bar 添加bar.num = 3將產生與您所想的完全相同的結果。 或者至少我希望你在想...

this代表了代碼執行的范圍。 在您的情況下,它是全局作用域window

JavaScript中的原型只是具有屬性和方法的對象。 您可以向其中添加成員,也可以從中繼承。 您可以閱讀本文以獲取更多信息。

讓我們分解一下代碼,一一看一下。

  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() {}; ,因此該函數無法讀取其num屬性,因此其輸出為undefined

這是指當前范圍。

如此說來,這就是為什么您逐步獲得結果的原因

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

})();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM