[英]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
秒。
在這種情況下,在程序的前面,您創建了一個名為f
的foo
實例。 然后,將名為num
的f
屬性設置為1
。
out
是f
的擴展名foo
的原型console.log
提供的功能,此對象是要調用其上下文的對象的num
屬性(在本例中為f
)。
因此, f.out();
打印1
。
foo.prototype.out.call(b);
call
是Function
對象原型上的一個函數。 call
在第一個參數的上下文中調用一個函數。 本質上,這一行( foo.prototype.out.call(b);
)與執行b.out();
相同b.out();
因為b
作為上下文參數傳遞。
該行輸出的其余解釋與最后一行的解釋完全相同
foo.prototype.out.call(bar);
在最后一行,你調用out
對bar
。 bar
是一個Function對象。 bar
沒有num
屬性,因此bar.num
是undefined
。
這並不是說您不能像使用f
和b
一樣添加屬性來bar
顯示。 函數也是對象。 因此,您可以添加屬性以與對f
和b
完全相同的方式進行bar
。 添加bar.num = 3
將產生與您所想的完全相同的結果。 或者至少我希望你在想...
this
代表了代碼執行的范圍。 在您的情況下,它是全局作用域window
。
JavaScript中的原型只是具有屬性和方法的對象。 您可以向其中添加成員,也可以從中繼承。 您可以閱讀本文以獲取更多信息。
讓我們分解一下代碼,一一看一下。
f.out();
這也指以下對象
var f = new foo(); f.num = 1; //Here you define a property `num` as 1
然后,當您調用f.out()
,原型函數將簡單地記錄num
foo.prototype.out.call(b);
在這里,您可以直接訪問該函數並將對象傳遞給該函數。 因此,當執行該方法時, this
代表通過的對象,因此最終記錄了它的值。
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.