Javascript是一種基於原型的語言,和咱們一般的Class based programming有很大的區別:編程
1. 函數式first class object,也就是說函數與對象具備相同的語言地位
數組
2. 沒有類,一切基於對象函數
3. 函數也是一種對象,所謂的函數對象
this
4. 對象是按引用來傳遞的
spa
每一個韓式都有一個prototype屬性,這個屬性指向一個對象的引用,這個對象成爲原型對象,源性對象包含函數實例共享的方法和屬性,也就是說講函數用做構造函數調用(使用new操做符調用)的時候,新建立的對象會從原型對象上繼承屬性和方法。prototype
先來弄清一個概念:
orm
私有變量,函數對象
JavaScript的做用域鏈,通俗講就是函數內定義的變量和函數若是不對外提供接口,那麼外部將沒法訪問到,就成爲了私有變量和私有函數。繼承
代碼以下: |
function Obj(){接口 var a = 0; //私有變量 var fn = function(){ } //私有函數 } |
這樣的函數對象Obj外部沒法訪問變量a和函數fn,他們變成私有的,只能在Obj內部使用,即便是函數Obj的實例仍然沒法訪問這些變量和函數。 |
靜態變量、函數
當定義一個函數後經過 「.」爲其添加的屬性和函數,經過對象自己仍然能夠訪問獲得,可是其實例卻訪問不到,這樣的變量和函數分別被稱爲靜態變量和靜態函數,用過Java、C#的同窗很好理解靜態的含義。
複製代碼代碼以下:
function Obj(){ |
實例變量、函數
在面向對象編程中除了一些庫函數咱們仍是但願在對象定義的時候同時定義一些屬性和方法,實例化後能夠訪問,JavaScript也能作到這樣
function Obj(){ this.a=[]; //實例變量 this.fn=function(){ //實例方法 } } console.log(typeof Obj.a); //undefined console.log(typeof Obj.fn); //undefined var o=new Obj(); console.log(typeof o.a); //object console.log(typeof o.fn); //function |
新的實例會有新的引用
function Obj(){ this.a=[]; //實例變量 this.fn=function(){ //實例方法 } } var o1=new Obj(); o1.a.push(1); o1.fn={}; console.log(o1.a); //[1] console.log(typeof o1.fn); //object var o2=new Obj(); console.log(o2.a); //[] console.log(typeof o2.fn); //function |
上面的代碼運行結果徹底符合預期,但同時也說明一個問題,在o1中修改了a和fn,而在o2中沒有改變,因爲數組和函數都是對象,是引用類型,這就說明o1中的屬性和方法與o2中的屬性與方法雖然同名但卻不是一個引用,而是對Obj對象定義的屬性和方法的一個複製。
這個對屬性來講沒有什麼問題,可是對於方法來講問題就很大了,由於方法都是在作徹底同樣的功能,可是卻又兩份複製,若是一個函數對象有上千和實例方法,那麼它的每一個實例都要保持一份上千個方法的複製,這顯然是不科學的,這可腫麼辦呢,prototype應運而生。