| 包裝類 | 類型名 | 常見值 | 分類 |
| Number | number | 123.123 | 基本數(shù)據(jù)類型 |
| Boolean | Boolean | true、false | 基本數(shù)據(jù)類型 |
| String | string | “hello world!” | 基本數(shù)據(jù)類型 |
| Object | object | {}、[] | 復(fù)合數(shù)據(jù)類型 |
| Function | function | function(){} | 特殊類型 |
| 無 | undefined | undefined、未定義 | 小數(shù)據(jù)類型 |
| 無 | null | null | 小數(shù)據(jù)類型 |
內(nèi)置類型與本文關(guān)系不大,不列出。
引用類型:object function
值類型:number、boolean、string、null、undefined
關(guān)于 prototype 的設(shè)計模式就不多說了,網(wǎng)上很多介紹,以一個例子介紹一下 js 中使用 new 構(gòu)造對象的過程。
function classname(){this.id=0;} var v=new classname();
當使用 function 構(gòu)造對象時,進行以下流程:
封裝這個大家都明白,在 js 中,重點在于訪問權(quán)限。在其他原生支持面向?qū)ο笳Z言中,一般支持 public、protected、private 三個關(guān)鍵字來控制訪問權(quán)限,但在 js 中,我們只能依靠復(fù)雜的作用域關(guān)系來控制:
function classname(a){
var uid=a; //uin 為模擬 private,作用域為 {},外部無法使用
this.getuid=function(){return a;} // 為 uid 提供一個外部只讀接口 obj.getuid();
this.setuid=function(val){a=val} // 為 uid 提供一個外部可寫接口 obj.setuid(5);
this.id=uid; //id 為模擬 public obj.id 使用
}
classname.prototype.func=function(){}; // 模擬 public 方法 obj.func() 調(diào)用
classname.stafunc=function(){}; // 模擬靜態(tài)方法 classname.stafunc() 調(diào)用
var obj=new classname(1);
[!] 非常需要注意的就是,因為 function 是引用類型, classname.prototype.func 是所有對象共享的一個 function 對象(每個對象僅存著引用),因此對象規(guī)模不大。而使用 this.getuid 和 this.setuid 為定義一個 function,因此每個對象實例都會存一份,如果放肆使用這種方法,會造成對象規(guī)模龐大,影響性能。個人認為模擬 private 變量的意義不大。
[!] 如果有需求真的需要大量使用 this.xxx=function(){} 這種情況,在 function(){} 中的 this 指針與最外的 this 指針是不同的,最好在類定義的首行加上 var _this=this;,這樣在 this.xxx=function(){} 中也可以方便使用綁定的指針。
繼承的實現(xiàn),主要有 2 種方法:第一種是使用 javascript 本身的原型模型,通過給 prototype 賦值并改變其 constructor 屬性來實現(xiàn)繼承;第二種方法是不使用 prototype,手動實現(xiàn)將父對象的所有屬性方法深拷貝到子對象。比如 A 需要繼承 B,第一種寫法可以:A.prototype=new B();A.prototype.constructor=A; 第二種寫法可以寫一個遞歸,或者使用 jquery 中的方法 extend。另外,如果要實現(xiàn)多繼承的話,prototype 就真的好麻煩了(需要依次多個類,還要建空對象來接),第二種方法就比較簡單,依次拷貝即可。一般這種繼承為了找父類方便,可以在對象中加個屬性,引用父類。
函數(shù)重載就不說了,都會,檢查參數(shù)即可,很靈活。隱藏屬性就是直接賦值 undefined。需要注意的是,如果是打算繼承 B 類的 prototype,一定要建一個空對象來接,否則的話,你給類寫方法的話,相當于直接修改了 prototype,就算不寫方法,你最后修改 constructor 時也會造成繼承鏈錯亂,接個空對象很容易:
function temp(){};
temp.prototype=B;
var obj=new temp();
這樣再讓需要繼承 B.prototype 的類繼承 obj 即可,即便修改 prototype 也不會影響到 B。而且也不像繼承 new B() 那樣浪費很多空間。
這個和其他語言中沒什么區(qū)別,淺拷貝就是直接拷貝,遇到引用類型或類類型不再深入。深拷貝則是根據(jù)類型判斷,進行遞歸拷貝。
這個值主要是用于維護繼承的原型鏈。一篇文章已經(jīng)寫的非常詳細,請參考:http://bbs.51js.com/thread-84148-1-1.html
由于我不是前臺開發(fā)人員,見過項目有限,僅談自己的經(jīng)驗。
我開發(fā)過的 B/S,常用兩種架構(gòu),一種是以 CGI 為主,由后臺語言去生成 HTML,JS 僅僅做一些用戶交互,ajax 通信等。另外一種是使用 MVC,后臺語言僅僅生成 JSON,View 層完全由 JS 組件在客戶端實現(xiàn)。后者一般大量使用面向?qū)ο蟮乃枷脒M行編程,將組件封裝成類,將 JSON 傳入構(gòu)造函數(shù),再由控制器或布局組件 Add 進來。由于組件可以重用,在開發(fā)后臺管理系統(tǒng)、JS 游戲上,效率還是很可觀的。