js面向(基於)對象編程——類(原型對象)與對象
this—問題提出
請大家先看一段代碼:
<html> <head> <script language="javascript"> function Person(){ } var p1=new Person(); p1.name="順平"; p1.age=60; window.alert(p1.name+" "+p1.age); var p2=new Person(); window.alert(p2.name); //這裡會輸出什麼。(undefined)</script> </head> <body></body> </html>
在實際編程中,我們可能有這樣的需求,當我們建立一個對象後,就希望該對象自動的擁有某些屬性(比如:當我們建立一個Person對象後,就希望該對象自動擁有name和age屬性,這又怎麼辦。)
解決之道:使用this
js虛擬機器會給每一個對象分配this,代表當前對象。坦白的講,要明白this(我的)不是件容易的事情,給大家打一個比方(上帝造人小故事)
function Person(){ this.name="abc" this.age=90; } var p1=new Person(); var p2=new Person(); p2.name="順平"; window.alert(p1.name+" "+p2.name); //輸出 abc 順平
補充知識:在定義的類(原型對象)中,使用 var 和 this 定義屬性有什麼區別。
<html> <head> <script language="javascript"> function Person(){ var name="abc"; //如果這樣去使用 name這個屬性是私人的 var age = 90;this.name2="abc2"; //this.name2 加this表示name2這個屬性是公開的 //this.show()就是Person的一個公開方法 //如果你一定要訪問私人屬性,則需要定義一個公開方法(特權方法) this.show=function(){ window.alert(age+" "+name); //name屬性是私人的 } //show2()這個是私人方法,只能在Person類中使用 //如果想在外部使用show2,可以在this.show中調用 //javascript中大部分方法都是公開的 function show2(){ window.alert("show2()"+age+" "+name);} } var p1=new Person(); //這樣調用name屬性,會報undefined window.alert(p1.name); window.alert(Person.name); //這個輸出什麼。 輸出 Person //name2屬性是公開的 window.alert(p1.name2); //輸出 abc2 //如果要訪問私人屬性name,就要在類中定義一個公開的方法,比如定義一個show方法 p1.show(); //輸出90 abcp1.show2(); //這裡會報錯</script> </head> <body><body> </html>
為了進一步理解this,再看一個程式
下面的程式應該好好理解,很重要
<html> <head> <script language="javascript"> function test1(){ alert(this.v); } var v=90; test1(); //test1()這個函數,從物件導向的角度看,它應該是屬於某個對象的,它就是屬於window的window.test1();// 輸出什麼? 等價於執行 test1(); // alert("ok"); 等同於 window.alert("ok"); //哪個對象執行個體調用this所在的函數,那麼this就代表哪個對象執行個體 //window.test1(); this就是window,進去了以後,調test1,//如果test1裡面有this,那個這個this就是調用者window,//這個this有沒有v呢,在外面定義了一個v=90,window對象是全域對象。 window.alert(v); //輸出v window.alert(window.v) //同樣輸出的v,和上面的一樣的//window對象是全域對象,在上面的test1函數中alert(this.v);,//不就是等同於alert(window.v);嗎,這樣就容易理解了 //什麼叫當前對象是this呢 function Person(){ this.abc=function(){ window.alert(this.v); //這裡的this就是p,誰調用this,this就是誰 } } var p=new Person(); p.v="hello"; //動態 p.abc(); //p調用abc,p就是裡面的this,而this確實有v這個屬性,則hello就被輸出了 </script> </head> <body></body> </html>
應該這麼去想:
alert("ok");
window.alert("ok");這兩個是一個意思,alert這個函數預設就是window對象。
我們過去調用函數是這樣寫
test1(); 這個就是前面沒有寫window而已,它和下面的是一樣的。
window.test1();
再看一下下面的記憶體分析圖
在上圖中,剛開始建立的時候堆0x1234中什麼都沒有,然後p.v="hello";,就在堆0x1234中放入了 資料,緊接著p.abc();調用函數,調用函數就開闢新棧了,在新棧裡面this就被傳進去了,此時這個this實際上就等價於p,p是對象,實際上傳 了地址,this就指向了ox1234,this.v,this是個地址就到堆中尋找,則hello就被輸出了。在記憶體配置圖中分析,就能理解的透徹了。誰調 用這個函數,誰就是這個this
javascript中的 HTML DOM window對象
window對象是javascript層級中的頂級對象。
window對象代表一個瀏覽器視窗或一個架構
window對象會在<body>或<frameset>每次出現時被自動建立
window對象表示一個瀏覽器視窗或一個架構。在用戶端javascript中,window對象是全域對象,所有的運算式都在當前的環境中計算。也就是說,要引用當前視窗根本不需要特殊的文法,可以把那個視窗的屬性作為全域變數來使用。例如,可以唯寫document,而不必寫window.document。
同樣,可以把當前視窗對象的方法當做函數來使用,如可唯寫alert(),而不必寫window.alert()。
記住一句話:
哪個對象執行個體調用this所在的函數,那麼this就代表哪個對象執行個體。
this——注意事項
this不能在類定義的外部使用,只能在類定義的方法中使用。在類定義的外部,調用者就變成window了
<html> <head> <script language="javascript"> function Person(){ this.abc=function(){ window.alert(this.v); //這裡的this就是p,誰調用this,this就是誰 } } var p=new Person(); p.v="hello"; //動態 p.abc(); //p調用abc,p就是裡面的this,而this確實有v這個屬性,則hello就被輸出了 window.alert(this.v); //在類定義的外部這樣使用,此時的this指的是window了,就變成另外一個對象了, //它並會把p.v的hello輸出,因為在類的外部這個this已經指的是window了</script> </head> <body></body> </html>
類——如何定義類