一、引言
長久以來,JavaScript在Web開發中一直處于被忽視的地位,甚至有相當一部分開發人員對它產生了誤解,認為JavaScript只不過是用來完成一些花哨功能的雕蟲小技。網絡上廣為流傳的低質量的JavaScript代碼對此也起到了推波助瀾的作用...很多應用中JavaScript都采用了面向過程的編程方式,代碼的可擴展性不好,復制粘貼的代碼比比皆是...
隨著Ajax等技術的廣泛使用,YUI、Prototype等對JavaScript的應用可謂是淋漓盡致、出神入化。人們才發現原來JavaScript可以實現如此強大的功能,具備如此優雅的架構...
二、準備
1、概念
JavaScript是一種弱類型語言。包括:
基本類型:數字Number,字符串String,布爾值Boolean;
復合類型:對象Object,數組Array;
工具類型:全局對象Global,日期Date,數學對象Math,正則表達式RegExp,錯誤對象Error;
特殊類型:函數Function。
這里我只想說兩點:
1)基本數據類型的包裝對象
每一個基本數據類型都有一個對應的對象類。可以靈活地實現類型轉換。簡單地說,JavaScript不僅支持數字、字符串和布爾值這些數據類型,還支持Number、String、Boolean類,這些類是基本數據類型的包裝(wrapper)。
例子:
var s="some string";
var len=s.length;
這里,s保存了一個字符串,原始的字符串值是不會改變的。一個新的String對象被創建了,實現了對長度屬性的訪問,之后它就被銷毀了。
其它例子:
var a="some string";
var b=new String("some string");
var c=["a","b","c"];
var d=new Array("a","b","c");
alert(typeof a);//string
alert(a instanceof String);//false
alert(a instanceof Object);//false
alert(typeof b);//object
alert(b instanceof String);//true
alert(b instanceof Object);//true
alert(typeof c);//object
alert(c instanceof Array);//true
alert(c instanceof Object);//true
alert(typeof d);//object
alert(d instanceof Array);//true
alert(d instanceof Object);//true
2)Function類型
做為JavaScript的一種特殊類型,我們將看到函數在面向對象編程中起到了非常關鍵的作用。
2.值和引用
類型 |
復制 |
傳遞 |
比較 |
數字 |
值 |
值 |
值 |
布爾值 |
值 |
值 |
值 |
字符串 |
不可變的 |
不可變的 |
值 |
對象 |
引用 |
引用 |
引用 |
函數 |
引用 |
引用 |
引用 |
數組 |
引用 |
引用 |
引用 |
例子:
var s1="hello";
var s2="hell"+"o";
alert(s1==s2);//true
var d1=new Date();
var d2=new Date();
alert(d1==d2);//false
3.this
在構造函數中,指代新創建的對象實例;
在對象的方法被調用時,指代調用該方法的對象實例。
4.arguments
arguments屬性由解釋器創建,用于訪問函數對象的每一個參數。
5.callee,caller
arguments的callee屬性獲取對正在執行的Function對象的引用;
Function對象的caller屬性獲取正在調用當前函數的父函數對象。
6.apply,call
兩者都是將函數綁定到其它對象上執行的,區別在于調用方式:
apply([thisObj[,argArray]])
call([thisObj[,arg1[,arg2[,[,.argN]]]]])
7.匿名函數
(function(a,b){
return a+b;
})(1,1);
等價于:
function f(a,b){
return a+b;
}
f(1,1);
8.null,undefined
null是JavaScript的關鍵字,表示空值。可以看作Object類型的一個特殊值。
undefined不是關鍵字,它是一個全局變量,使用了未定義變量、變量未賦值、void運算符,都會返回“undefined”。
9.constructor
從JavaScript1.1開始,每個對象都具有一個constructor屬性,它引用的是用來初始化該對象的構造函數。
10.prototype
JavaScript1.1引入了原型對象的概念,每一個對象都有一個原型對象,對象可以繼承它的原型對象的所有屬性和方法。
要為一個對象的類制定原型對象,需要將構造函數的prototype屬性設置為指定的對象。之后,如果用構造函數初始化對象時,會自動將指定的對象作為新創建對象的原型對象。
注意:
1)使用原型對象可以減少每個繼承對象的內存需求量;
2)即使屬性是在對象被創建后才加到它的原型對象中的,對象也能夠繼承這些后定義的屬性。
3)當調用一個對象的一個屬性時,先在該對象定義內查找該屬性,如果沒有該屬性才到該對象的原型對象中查找,依此類推。
三、實現
在面向對象編程中,我們可以把過程編程中的一個個function看作一個個獨立定義的類,函數名即為類名。
1.例子:Circle類
function Circle(radius){
//實例變量
this.r=radius;
}
//靜態變量
Circle.PI=3.14159;
//實例方法
Circle.prototype.area=function(){
return Circle.PI*this.r*this.r;
}
//靜態方法
Circle.max=function(a,b){
if(a.r>=b.r){
return a;
}
else{
return b;
}
}
//調用
var a=new Circle(2);
var b=new Circle(3);
var c=a.area();
var d=Circle.max(a,b);
2.繼承
1)一種繼承方式
//這里我們將CircleMore類的prototype指向了一個Circle類實例,
//并增加了circumference方法。
function CircleMore(radius){
this.r=radius;
}
CircleMore.prototype=new Circle(0);
CircleMore.prototype.circumference=function(){
return 2*Circle.PI*this.r;
}
這樣能夠實現對Circle的繼承,但是這里存在一點問題:我們直接把CircleMore類的prototype指向了一個Circle類實例,這樣就覆蓋了JavaScript提供的原型對象,而且拋棄了給定的constructor屬性,這樣CircleMore的constructor屬性就指向了父類Circle的constructor屬性。而且這種方式總是使人感覺怪怪的。
2)Ajax架構Prototype(區別前面提到的prototype哦)的繼承方式
//Prototype框架為Object對象定義了extend方法,
//將source的屬性和方法復制到了destination。
Object.extend = function(destination, source) {
for (var property in source)
destination[property] = source[property];
return destination;
};
//調用
function ParentClass(){...}
function SubClass(){}
SubClass.prototype=Object.extend({
newMethod:function(){
alert("newMethod");
}
},
ParentClass.prototype
);
3)如果這里對兩個參數交換位置,則是對原對象的開展。
例子:通過extend方法對String對象進行了擴展
Object.extend(String.prototype,{
newMethod:function(){
alert("newMethod");
}
});
3.多態
Object.extend = function(destination, source) {
for (var property in source)
destination[property] = source[property];
return destination;
}
//基類
function base(){}
base.prototype={
initialize:function(){
this.oninit();//調用了一個虛方法
}
}
//子類SubClassA
function SubClassA(){}
SubClassA.prototype=Object.extend({
//...其它屬性方法
prop:"SubClassA",
oninit:function(){
alert(this.prop);
}},
base.prototype
}
//子類SubClassB
function SubClassB(){}
SubClassB.prototype=Object.extend({
//...其它屬性方法
prop:"SubClassB",
oninit:function(){
alert(this.prop);
}},
base.prototype
}
//調用
var a=new SubClassA();
var b=new SubClassB();
a.initialize();//輸出"SubClassA"
b.initialize();//輸出"SubClassB"
四、JavaScript與設計模式
1.Singleton
function Singleton(){
if(Singleton.caller!=Singleton.getInstance){
throw new Error("Can not new Singleton instance!");
}
this.prop="some string";
//...
}
Singleton._instance=null;
Singleton.getInstance=function(){
if(this._instance==null){
this._instance=new Singleton();
}
return this._instance;
}
var a=Singleton.getInstance();
var b=Singleton.getInstance();
b.prop="another string";
alert(a.prop);//"another string"
alert(b.prop);//"another string"
2.Factory
function XMLHttpFactory(){}
XMLHttpFactory.createXMLHttp=function(){
if(...){
return new XMLHttpRequest();
}
else if(...){
return new ActiveXObject("MSXML2.XMLHttp");
}
...
}
var xmlhttp=XMLHttpFactory.createXMLHttp();
五、備注
參考資料:
《JavaScript權威指南(第三版)》 中國電力出版社
《JavaScript高級程序設計與應用實例》 人民郵電出版社
Prototype 1.6.0
YUI 2.3.1
注:原文(
http://www.cnblogs.com/charming/archive/2007/11/25/972110.html)