JavaScript 面向對象基礎

1  關於對象的javascript

1  關於對象的靜態屬性、私有屬性、局部變量、原型變量 的使用與區別

1)局部變量:是指在函數中用 var 聲明過的變量,在函數運行完以後內存被自動回收!java

2)私有屬性:是指在函數中用 this 標記過的變量,在實例對象後一直被對象所獨有!安全

3)靜態屬性:是指函數(類)自己所獨有的屬性,他是不能被實例對象所調用的,這與java不一樣。閉包

4)原型變量:是指經過類或者對象自己的原型所所建立的變量,他能被全部的實例對象以及類自己原型所共享。函數

具體以下:ui

function Person( ){ 
this.name = 'zhangsan' ;                        // 私有屬性
var value = 'wuyun' ;                             // 局部變量
this.process  = function(){                    // 使用方法    
console.info(this.name + value ); // 若是局部變量和私有變量同名,那麼會使用局部變量,因此使用this做爲標記!
 }}
var person = new Person( );
console.info(   person.__proto__  == Person.prototype   );  // true,說明兩者能夠經過原型相互共享屬性
Person.age = 21 ;                                          // Person的靜態屬性,person是沒法調用的
person.age = 22 ;                                         // person的靜態屬性,Person是沒法調用的
Person.prototype.sex = 'man' ;                  // 原型變量,兩者共享
person.__proto__.height = 185 ;               // 原型變量,兩者共享


2 關於prototype 和 __proto__ 的調用this

1)prototype 是Function對象獨有的屬性,也就是說只有類纔可以調用這個屬性prototype

2)__proto__  是實例對象獨有的屬性,也就是用new,或者{ } 聲明過的變量才能調用code

3)以上兩者若是是對應類的實例的話,那麼他們引用的是同一個原型,因此 person.__proto__ == Person.prototype  爲 trueorm


3 關於原型鏈繼承(必不可少的兩步)

1)子類的原型指向父類的實例,SubClass.prototype = new SuperClass( );

2)子類的原型構造函數指向子類自己,SubClass.prototype.constructor = SubClass ; 

3 ) 因爲js使用原型繼承致使,構造函數也別繼承,然而面向對象來講這是錯誤的,因此纔有第二步從新指向構造函數。

4 ) 我的理解 Person 與 Person.prototype 的差別是:前者是指構造函數或類自己,後者實際上是一個全部實例都共享的實例對象。

5)若是單純只是繼承某一個函數那麼可使用 call 函數進行處理,而無需繼承。 Class.method.call(Self , param) ; 

具體以下:

function extends( SubClass , SuperClass){
/*第一步 : 構建橋樑類Bridge,他的做用就是徹底替代父類自己,包括構造方法*/
var Bridge = function( ){ } ;Bridge.prototype = new SuperClass( );
 // Bridge.prototype.constructor = SuperClass ;這一步原型鏈默認完成 
 /*第二步 : 使用子類的原型鏈繼承橋樑父類*/
 SubClass.prototype = new Bridge( );  SubClass.prototype.constructor = SubClass ; 
  /*第三步 : 擴展子類屬性,把父類的引用做爲子類的共享屬性,爲子類中所調用 */
  SubClass.prototype.superClass = SuperClass.prototype ;     
 //  這裏必須是prototype,而不能是函數自己
 /*第四步 : 爲保證程序正常運行機制,作個小判斷*/
 if( SuperClass.prototype.constructor == Object.prototype.constructor  ){SuperClass.prototype.constructor = SuperClass ;} }


6)javascript是單繼承的,但若是想在一個類中擁有多個類的方法,那麼就要使用聚合(摻元類,把其餘類的方法爲本身所用)。


4 關於接口的三種模仿方式

1)註釋式模仿接口(其實就是用註釋語句把接口給解釋,說白了就是經過規範文檔來講明某給類就是一個接口),以下/*  這裏就是接口的註釋聲明文檔,這個是核心

interface Composite {    function add(child);    function remove(child);    function getChild(index);}interface FormItem {    function save();} */

var CompositeForm = function(id, method, action) { //自定義任意一個類,用來模擬實現接口

    ...

};

CompositeForm.prototype.add = function(child) { // 經過實現方法說明實現接口

    ...

};

2)屬性檢查式模仿接口(一樣使用註釋,可是它與上面的惟一不一樣點就是在方法的實現中,對該類有個判斷是否實現了該接口,所謂判斷,就是該類有一個屬性用來保存他實現類的名稱,因此稱之爲屬性檢查)function addForm(formInstance) {    if(!implements(formInstance, 'Composite', 'FormItem')) {        throw new Error("Object does not implement a required interface.");    }    ...}3)鴨式辨型式模仿接口(它採用的思想是說只要在實現類中實現了接口中的全部方法就等同於實現了接口,那麼他的核心就是判斷是否實現了接口中的方法,不然報錯)


5 建立對象的模式(成員變量的保護)

1)門戶大開型(使用 this.property 的方式定義成員變量,可是爲了成員數據的安全性,咱們使用接口實現,只能調用接口來訪問成員變量,不過這必須自覺遵照,由於自己是能夠直接經過instance.property 調研的)function Book( id , name ){this.setId(id); //使用接口方法對屬性賦值,而不是直接賦值屬性this.setName(name);}Book.prototype = {  // 經過字面量方式註冊實現接口的方法,同時還使用檢查規則,這樣就避免了本身賦值屬性致使的問題setId:function(id){this.checkId(id); // 這個纔是核心this.id = id ;}check:function(id){// some code}.......}2)用戶命名規範區別私有成員(這種方法其實和上面的方法是如出一轍的,惟一的差別就在於對象的成員變量名稱都用下劃線開頭,一些不但願外部調用的方法也使用下劃線開頭,說白了這就是約定俗成,並非真正的達到目的)以下:Book.prototype = { // 經過字面量方式註冊實現接口的方法,同時還使用檢查規則,這樣就避免了本身賦值屬性致使的問題setId:function(id){this._checkId(id); // 這個纔是核心this._id = id ;

}

_check:function(id){

// some code

}

.......

}

3)使用閉包函數實現真正的私有成員(這種作法就是充分借用函數做用域以及閉包原來達到私有成員變量的保護)

1)函數做用域:在javascript中只有函數做用域沒有塊級做用域,換句話說,若是A函數內部有個B函數,那麼B函數是可以調用A函數的全部成員的。

2)閉包:對以上的A B , 若是在B中使用了A的成員變量,無論B在哪裏執行,是在A內部執行,或是在A外部的任意函數做用域中執行,B所執行的做用域仍是A,也就是說無論A是否執行完,A都會爲B保留一份執行空間的內存,那麼B使用A的成員變量將會被保留。這就是說 在不一樣函數做用域中也能調用以前做用域的成員變量,爲閉包!

3)使用函數做用域和閉包的概念完成私有成員的保護:

var Book = function(newIsbn, newTitle, newAuthor) { // implements Publication  // Private attributes. 私有成員變量  var isbn, title, author;  // Private method. 私有方法  function checkIsbn(isbn) {    ...  }  // Privileged methods. 公共方法  this.getIsbn = function() {    return isbn;  };  this.setIsbn = function(newIsbn) {    if(!checkIsbn(newIsbn)) throw new Error('Book: Invalid ISBN.');    isbn = newIsbn;  };  // Constructor code. 初始化  this.setIsbn(newIsbn);};// Public, non-privileged methods. 公共共享方法Book.prototype = {  display: function() {    ...  }};

這裏很值得注意的是:使用 var 聲明的變量就是爲私有的屬性,由於沒有使用this標記因此是沒法再外部調用的,可是經過閉包達到私有變量的保護有個很大的缺點就是:公共方法(爲了閉包)寫在了類裏面,從而致使每一個對象實例化後都會保存這個方法的副本,那麼致使佔了大量內存,若是把方法寫在prototype中,即成爲公共共享的方法,只保存一份副本在內存,可是在公共共享的方法中只能使用this來調用變量,而不能調用用var聲明的變量。因此這就是這種方法的弊端!並且還有一個弊端就是:繼承該類以後的子類是不能訪問到該類的私有成員的,由於只能使用閉包訪問了!!!


6 關於屬性和方法的相關概念

1)實例公共屬性: this.name

2)實例私有屬性: person.name(單個實例);var name ( 全部實例 )

3)類公共屬性:Person.name ; 

4 ) 靜態屬性:Person.prototype.name ; person.__proto__.name ;

5)使用閉包從新定義屬性的概念:

var Person = ( function( ){var name = ''; //類的靜態私有屬性this.sex = '';   // 類的靜態共有屬性var ocr = function( ){var age = ''; //實例私有屬性this.height = ''; //實例共享屬性}ocr.getName = function( ){ //定義類的方法return name ;}return ocr ; //返回的是類自己} )( )alert(Person.getName( ));

這裏說說執行流程:1)使用小括號就是爲了讓他自動執行,這裏直接使用Person,實際上已經把Person定義的function執行完成了,等價於沒有小括號時的,Person();

                               2)返回一個function,實際上就是閉包的原理,也能夠當作就是返回一個類,是這個類自己而不是類實例,因此咱們定義方法是用類名定義類的屬性,而不是定義實例屬性,否則的話沒法在外面調用。


7 常量(就是使用屬性的定義以及閉包原理)


8 函數的鏈式調用

1)所謂鏈式調用不過就是能夠person.fn( ).process( ).property ;

2)實現很簡單,就是在每個方法的返回值爲當前實例,即 this ; 

3)關於Jquery 的鏈式調用,以下:

//爲了類(Function)擴展函數,咱們頂一個他的靜態函數

Function.prototype.method = function(name,fn){ // Function.prototype是爲全部的Function對象增長屬性,緣由是繼承

 this.prototype[name] = fn;  // 這裏的this是指函數類自己,因此要用prototype,這樣才能使屬性共享  return this;  // 返回this,達到鏈式調用

};

相關文章
相關標籤/搜索