面向?qū)ο蟮腏avascript之一(初識Javascript)
更新時間:2012年01月20日 17:42:35 作者:
Javascript是一門極富表現(xiàn)力的語言,在當(dāng)今大行其道的Web浪潮中扮演著非常關(guān)鍵的作用。合理、高效地利用這門技術(shù),可以讓我們的Web世界多姿多彩。首先,我們認(rèn)識一下這門技術(shù)的幾個獨特的特性
1. Javascript最大的特性在于其靈活性。作為一名前端開發(fā)人員,既可以采用函數(shù)式的編程風(fēng)格,也可以采用更復(fù)雜一點的面向?qū)ο蟮木幊田L(fēng)格。不管你采用哪種風(fēng)格,都可以完成一些非常有用的任務(wù)。因而,Javascript是一門面向過程的語言,同時也是一門面向?qū)ο蟮恼Z言,進(jìn)而可以模仿面向?qū)ο笳Z言的編程模式和慣用法。我們用一個例子來說明:啟動和停止動畫。
如果你習(xí)慣于函數(shù)式的編程風(fēng)格,代碼會如下:
function startAnimation() {
//啟用動畫
}
function stopAnimation() {
//停止動畫
}
這種方法很簡單,但卻無法創(chuàng)建保存狀態(tài)以及僅對內(nèi)部狀態(tài)進(jìn)行操作的動畫對象。下面我們定義一個類:
var Animation = function() {
//動畫類
};
Animation.prototype.start = function() {
//啟用動畫
};
Animation.prototype.stop = function() {
//停止動畫
};
/*用法如下*/
var anim = new Animation();
anim.start();
anim.stop();
如果你想將類的定義封裝到一條聲明中,則代碼如下:
var Animation = function() {
//動畫類
};
Animation.prototype = {
start: function(){
//啟用動畫
},
stop: function(){
//停止動畫
}
};
這樣讓面向?qū)ο蟮某绦騿T看起來更加眼熟,我們可以試著嘗試更復(fù)雜一點的寫法:
Function.prototype.method = function(name, fn){
this.prototype[name] = fn;
}
var Animation = function() {
//動畫類
};
Animation.method("start", function(){
//啟用動畫
});
Animation.method("stop", function(){
//停止動畫
});
我們?yōu)镕unction類擴展了一個方法method用于添加新方法。name代表函數(shù)名稱,fn代表函數(shù)的具體實現(xiàn)。在基于此寫法的基礎(chǔ)之上,我們可以讓函數(shù)支持鏈?zhǔn)秸{(diào)用:
Function.prototype.method = function(name, fn){
this.prototype[name] = fn;
return this;
}
var Animation = function() {
//動畫類
};
Animation.method("start", function(){
//啟用動畫
}).method("stop", function(){
//停止動畫
});
至此已經(jīng)見識了5種不同的編程風(fēng)格,具有不同的代碼量、編碼效率和執(zhí)行性能。你可以選擇最適合當(dāng)前項目的編程風(fēng)格來進(jìn)行工作。
2. Javascript是一門弱類型語言。聲明變量時不必指定類型,但并不代表沒有類型。Javascript包含三種基本類型:布爾型、數(shù)值型和字符串類型,此外還包含對象類型和函數(shù)類型,最后還包含空類型和未定義類型?;绢愋桶粗祩鬟f,其他類型按引用傳遞。可以根據(jù)變量賦值改變類型,基本類型之間可以相互轉(zhuǎn)換。toString()可以把數(shù)值或布爾值轉(zhuǎn)化為字符串,parseInt()和parseFloat()可以將字符串轉(zhuǎn)化為數(shù)值,雙"非"操作可以將字符串或數(shù)值轉(zhuǎn)化為布爾值。
3. Javascript函數(shù)是"一等"對象。函數(shù)可以存儲在變量中,可作為參數(shù)傳到其他函數(shù),可作為返回值從其他函數(shù)中傳出,也可在運行時構(gòu)造。在于函數(shù)打交道時,帶來了極大的靈活性和極強的表達(dá)能力,這些都是構(gòu)建面向?qū)ο蟮幕A(chǔ)??梢酝ㄟ^function() {...}創(chuàng)建匿名函數(shù)(沒有函數(shù)名,也可賦給變量)。下面以例子來說明:
(function(){
var a = 10;
var b = 5;
alert(a * b);//返回50
})();//函數(shù)定義就立即執(zhí)行
之所以能立即執(zhí)行,是因為函數(shù)聲明后的一對括號。但我們發(fā)現(xiàn),括號內(nèi)空無一物,也并非完全如此。
(function(a, b){
alert(a * b);//返回50
})(10, 5);//與前面等價
這個匿名函數(shù)與前一個等價,只是變量沒有在函數(shù)內(nèi)聲明,而是直接從外部傳入而已。其實,這個匿名函數(shù)也可以有個返回值,并賦給某個變量。
var c = (function(a, b){
return a * b;//返回50
})(10, 5);//與前面等價
alert(c);//50
匿名函數(shù)的最大用途是創(chuàng)建閉包。所謂閉包,就是一個受保護的變量空間,由內(nèi)嵌函數(shù)生成。由于Javascript具有函數(shù)級的作用域,即定義在函數(shù)內(nèi)部的變量在函數(shù)外部是不能被訪問的,函數(shù)僅運行在定義它的作用域中,而不是在調(diào)用的作用域中。這樣,就可以把變量包裹在匿名函數(shù)中加以保護。例如,你可以通過以下方式創(chuàng)建私有變量:
var c;
(function(){
var a = 10;
var b = 5;
c = function(){
return a * b;//返回50
}
})();
c();//c可以訪問a,b,即使它在匿名函數(shù)的外部也能被執(zhí)行
4. Javascript對象是"易變"的。一切都是對象(除了3種基本類型),而且所有對象都是易變的。這意味著你能使用一些別的語言不存在的技術(shù)。例如為函數(shù)動態(tài)添加屬性。
function displayError(error){
displayError.numTimesExecuted++;
alert(error);
}
displayError.numTimesExecuted = 0;//意味著可對預(yù)先定義的類和對象進(jìn)行修改
可以利用prototype機制在類的實例創(chuàng)建后再動態(tài)添加,此時對已定義的對象仍然有效。例如:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype = {
getName: function() {
return this.name;
},
getAge: function() {
return this.age;
}
};
//先定義兩個變量
var miracle = new Person("Miracle", 28);
var mike = new Person("Mike", 32);
//動態(tài)添加一個方法
Person.prototype.getGreeting = function() {
return "Hello " + this.getName() + "!";
};
//displayGreeting()僅對Miracle有效
miracle.displayGreeting = function() {
alert(this.getGreeting());
}
與對象的易變性相關(guān)的就是反射(也可稱為"內(nèi)省"),即在運行時檢查對象的屬性和方法,并利用這些信息來實例化類和執(zhí)行方法,甚至在開發(fā)時不需要知道它們的名稱。借助于對象的這兩大特性,可以完全模仿面向?qū)ο笳Z言的高級特性,但要記住在Javascript中任何對象都是可以在運行時修改。
5. Javascript具有實現(xiàn)"繼承"的天份。這里簡單提及一下:Javascript繼承包含"類式"繼承和基于對象的原型式繼承,這個話題我會在下一期的文章中詳細(xì)論述。
最后總結(jié)一下,之所以采用面向?qū)ο蠛驮O(shè)計模式的思想來處理Javascript這種看似過程式的語言,到底有什么好處呢?我總結(jié)了以下幾點供大家參考:
(1).可維護性。有助于降低模塊之間的耦合性,對項目中代碼可按模塊和功能職責(zé)來劃分。
(2).便于交流。對于一個大型團隊來說,可能用設(shè)計模式很簡單的術(shù)語可以高度概括你所負(fù)責(zé)實現(xiàn)的功能模塊,而不必太多讓團隊其他成員關(guān)注過多的細(xì)節(jié)。
(3).提升性能。利用模式可以減少傳送到客戶端代碼量的同時并提高程序運行的速度。
當(dāng)然,有利就有弊。弊端在于:
(1).復(fù)雜度相對較高。獲取可維護性的代價是以代碼的高度重構(gòu)和模塊化的劃分而成,對于一些新手來說,很難一下適應(yīng)。
(2).部分模式反而降低性能。但是這種拖累依賴于你的項目需求,可能有時微不足道,有時難以接受。
因此,建議大家學(xué)會理解設(shè)計模式的應(yīng)用場景,用對場景才是對設(shè)計模式的真正意義上的應(yīng)用。盲目應(yīng)用和用錯場景就是誤用,還不如不用。
如果你習(xí)慣于函數(shù)式的編程風(fēng)格,代碼會如下:
復(fù)制代碼 代碼如下:
function startAnimation() {
//啟用動畫
}
function stopAnimation() {
//停止動畫
}
這種方法很簡單,但卻無法創(chuàng)建保存狀態(tài)以及僅對內(nèi)部狀態(tài)進(jìn)行操作的動畫對象。下面我們定義一個類:
復(fù)制代碼 代碼如下:
var Animation = function() {
//動畫類
};
Animation.prototype.start = function() {
//啟用動畫
};
Animation.prototype.stop = function() {
//停止動畫
};
/*用法如下*/
var anim = new Animation();
anim.start();
anim.stop();
如果你想將類的定義封裝到一條聲明中,則代碼如下:
復(fù)制代碼 代碼如下:
var Animation = function() {
//動畫類
};
Animation.prototype = {
start: function(){
//啟用動畫
},
stop: function(){
//停止動畫
}
};
這樣讓面向?qū)ο蟮某绦騿T看起來更加眼熟,我們可以試著嘗試更復(fù)雜一點的寫法:
復(fù)制代碼 代碼如下:
Function.prototype.method = function(name, fn){
this.prototype[name] = fn;
}
var Animation = function() {
//動畫類
};
Animation.method("start", function(){
//啟用動畫
});
Animation.method("stop", function(){
//停止動畫
});
我們?yōu)镕unction類擴展了一個方法method用于添加新方法。name代表函數(shù)名稱,fn代表函數(shù)的具體實現(xiàn)。在基于此寫法的基礎(chǔ)之上,我們可以讓函數(shù)支持鏈?zhǔn)秸{(diào)用:
復(fù)制代碼 代碼如下:
Function.prototype.method = function(name, fn){
this.prototype[name] = fn;
return this;
}
var Animation = function() {
//動畫類
};
Animation.method("start", function(){
//啟用動畫
}).method("stop", function(){
//停止動畫
});
至此已經(jīng)見識了5種不同的編程風(fēng)格,具有不同的代碼量、編碼效率和執(zhí)行性能。你可以選擇最適合當(dāng)前項目的編程風(fēng)格來進(jìn)行工作。
2. Javascript是一門弱類型語言。聲明變量時不必指定類型,但并不代表沒有類型。Javascript包含三種基本類型:布爾型、數(shù)值型和字符串類型,此外還包含對象類型和函數(shù)類型,最后還包含空類型和未定義類型?;绢愋桶粗祩鬟f,其他類型按引用傳遞。可以根據(jù)變量賦值改變類型,基本類型之間可以相互轉(zhuǎn)換。toString()可以把數(shù)值或布爾值轉(zhuǎn)化為字符串,parseInt()和parseFloat()可以將字符串轉(zhuǎn)化為數(shù)值,雙"非"操作可以將字符串或數(shù)值轉(zhuǎn)化為布爾值。
3. Javascript函數(shù)是"一等"對象。函數(shù)可以存儲在變量中,可作為參數(shù)傳到其他函數(shù),可作為返回值從其他函數(shù)中傳出,也可在運行時構(gòu)造。在于函數(shù)打交道時,帶來了極大的靈活性和極強的表達(dá)能力,這些都是構(gòu)建面向?qū)ο蟮幕A(chǔ)??梢酝ㄟ^function() {...}創(chuàng)建匿名函數(shù)(沒有函數(shù)名,也可賦給變量)。下面以例子來說明:
復(fù)制代碼 代碼如下:
(function(){
var a = 10;
var b = 5;
alert(a * b);//返回50
})();//函數(shù)定義就立即執(zhí)行
之所以能立即執(zhí)行,是因為函數(shù)聲明后的一對括號。但我們發(fā)現(xiàn),括號內(nèi)空無一物,也并非完全如此。
復(fù)制代碼 代碼如下:
(function(a, b){
alert(a * b);//返回50
})(10, 5);//與前面等價
這個匿名函數(shù)與前一個等價,只是變量沒有在函數(shù)內(nèi)聲明,而是直接從外部傳入而已。其實,這個匿名函數(shù)也可以有個返回值,并賦給某個變量。
復(fù)制代碼 代碼如下:
var c = (function(a, b){
return a * b;//返回50
})(10, 5);//與前面等價
alert(c);//50
匿名函數(shù)的最大用途是創(chuàng)建閉包。所謂閉包,就是一個受保護的變量空間,由內(nèi)嵌函數(shù)生成。由于Javascript具有函數(shù)級的作用域,即定義在函數(shù)內(nèi)部的變量在函數(shù)外部是不能被訪問的,函數(shù)僅運行在定義它的作用域中,而不是在調(diào)用的作用域中。這樣,就可以把變量包裹在匿名函數(shù)中加以保護。例如,你可以通過以下方式創(chuàng)建私有變量:
復(fù)制代碼 代碼如下:
var c;
(function(){
var a = 10;
var b = 5;
c = function(){
return a * b;//返回50
}
})();
c();//c可以訪問a,b,即使它在匿名函數(shù)的外部也能被執(zhí)行
4. Javascript對象是"易變"的。一切都是對象(除了3種基本類型),而且所有對象都是易變的。這意味著你能使用一些別的語言不存在的技術(shù)。例如為函數(shù)動態(tài)添加屬性。
復(fù)制代碼 代碼如下:
function displayError(error){
displayError.numTimesExecuted++;
alert(error);
}
displayError.numTimesExecuted = 0;//意味著可對預(yù)先定義的類和對象進(jìn)行修改
可以利用prototype機制在類的實例創(chuàng)建后再動態(tài)添加,此時對已定義的對象仍然有效。例如:
復(fù)制代碼 代碼如下:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype = {
getName: function() {
return this.name;
},
getAge: function() {
return this.age;
}
};
//先定義兩個變量
var miracle = new Person("Miracle", 28);
var mike = new Person("Mike", 32);
//動態(tài)添加一個方法
Person.prototype.getGreeting = function() {
return "Hello " + this.getName() + "!";
};
//displayGreeting()僅對Miracle有效
miracle.displayGreeting = function() {
alert(this.getGreeting());
}
與對象的易變性相關(guān)的就是反射(也可稱為"內(nèi)省"),即在運行時檢查對象的屬性和方法,并利用這些信息來實例化類和執(zhí)行方法,甚至在開發(fā)時不需要知道它們的名稱。借助于對象的這兩大特性,可以完全模仿面向?qū)ο笳Z言的高級特性,但要記住在Javascript中任何對象都是可以在運行時修改。
5. Javascript具有實現(xiàn)"繼承"的天份。這里簡單提及一下:Javascript繼承包含"類式"繼承和基于對象的原型式繼承,這個話題我會在下一期的文章中詳細(xì)論述。
最后總結(jié)一下,之所以采用面向?qū)ο蠛驮O(shè)計模式的思想來處理Javascript這種看似過程式的語言,到底有什么好處呢?我總結(jié)了以下幾點供大家參考:
(1).可維護性。有助于降低模塊之間的耦合性,對項目中代碼可按模塊和功能職責(zé)來劃分。
(2).便于交流。對于一個大型團隊來說,可能用設(shè)計模式很簡單的術(shù)語可以高度概括你所負(fù)責(zé)實現(xiàn)的功能模塊,而不必太多讓團隊其他成員關(guān)注過多的細(xì)節(jié)。
(3).提升性能。利用模式可以減少傳送到客戶端代碼量的同時并提高程序運行的速度。
當(dāng)然,有利就有弊。弊端在于:
(1).復(fù)雜度相對較高。獲取可維護性的代價是以代碼的高度重構(gòu)和模塊化的劃分而成,對于一些新手來說,很難一下適應(yīng)。
(2).部分模式反而降低性能。但是這種拖累依賴于你的項目需求,可能有時微不足道,有時難以接受。
因此,建議大家學(xué)會理解設(shè)計模式的應(yīng)用場景,用對場景才是對設(shè)計模式的真正意義上的應(yīng)用。盲目應(yīng)用和用錯場景就是誤用,還不如不用。
您可能感興趣的文章:
- javascript this用法小結(jié)
- javascript 打印內(nèi)容方法小結(jié)
- javaScript 刪除確認(rèn)實現(xiàn)方法小結(jié)
- JavaScript在IE和Firefox(火狐)的不兼容問題解決方法小結(jié)
- 初識javascript 文檔碎片
- JavaScript/jQuery 表單美化插件小結(jié)
- javascript的console.log()用法小結(jié)
- JavaScript高級程序設(shè)計(第3版)學(xué)習(xí)筆記6 初識js對象
- javascript window.confirm確認(rèn) 取消對話框?qū)崿F(xiàn)代碼小結(jié)
- JavaScript window.document的屬性、方法和事件小結(jié)
- javascript if條件判斷方法小結(jié)
- Javascript獲取當(dāng)前時間函數(shù)和時間操作小結(jié)
- 初識Javascript小結(jié)
相關(guān)文章
javascript面向?qū)ο笕腴T基礎(chǔ)詳細(xì)介紹
本文章介紹了js中常用的對象包括有JavaScript對象簡介 字符串對象 date() 數(shù)組 數(shù)學(xué)對象 函數(shù)對象 應(yīng)用介紹,有需要了解的同學(xué)可參考一下2012-09-09javascript 面向?qū)ο?實現(xiàn)namespace,class,繼承,重載
這幾天老大天天嚷嚷要重構(gòu)我們寫的javascript,抱怨代碼太混亂,可讀性差,維護困難,要求javascript也按面對象的模型來重構(gòu)。2009-10-10