Javascript基礎知識篇(1): 初識Javascript


Javascript是一門極富表現力的語言,在當今大行其道的Web浪潮中扮演着非常關鍵的作用。合理、高效地利用這門技術,可以讓我們的Web世界多姿多彩。首先,我們認識一下這門技術的幾個獨特的特性。

1. Javascript最大的特性在於其靈活性。作為一名前端開發人員,既可以采用函數式的編程風格,也可以采用更復雜一點的面向對象的編程風格。不管你采用哪種風格,都可以完成一些非常有用的任務。因而,Javascript是一門面向過程的語言,同時也是一門面向對象的語言,進而可以模仿面向對象語言的編程模式和慣用法。我們用一個例子來說明:啟動和停止動畫。

如果你習慣於函數式的編程風格,代碼會如下:

function startAnimation() {
//啟用動畫
}
function stopAnimation() {
//停止動畫
}

這種方法很簡單,但卻無法創建保存狀態以及僅對內部狀態進行操作的動畫對象。下面我們定義一個類:

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(){
//停止動畫
}
};

 這樣讓面向對象的程序員看起來更加眼熟,我們可以試着嘗試更復雜一點的寫法:

Function.prototype.method = function(name, fn){
this.prototype[name] = fn;
}
var Animation = function() {
//動畫類
};
Animation.method("start", function(){
//啟用動畫
});
Animation.method("stop", function(){
//停止動畫
});

我們為Function類擴展了一個方法method用於添加新方法。name代表函數名稱,fn代表函數的具體實現。在基於此寫法的基礎之上,我們可以讓函數支持鏈式調用:

Function.prototype.method = function(name, fn){
this.prototype[name] = fn;
return this;
}
var Animation = function() {
//動畫類
};
Animation.method("start", function(){
//啟用動畫
}).method("stop", function(){
//停止動畫
});

至此已經見識了5種不同的編程風格,具有不同的代碼量、編碼效率和執行性能。你可以選擇最適合當前項目的編程風格來進行工作。

2. Javascript是一門弱類型語言。聲明變量時不必指定類型,但並不代表沒有類型。Javascript包含三種基本類型:布爾型、數值型和字符串類型,此外還包含對象類型和函數類型,最后還包含空類型和未定義類型。基本類型按值傳遞,其他類型按引用傳遞。可以根據變量賦值改變類型,基本類型之間可以相互轉換。toString()可以把數值或布爾值轉化為字符串,parseInt()和parseFloat()可以將字符串轉化為數值,雙"非"操作可以將字符串或數值轉化為布爾值。

3. Javascript函數是"一等"對象。函數可以存儲在變量中,可作為參數傳到其他函數,可作為返回值從其他函數中傳出,也可在運行時構造。在於函數打交道時,帶來了極大的靈活性和極強的表達能力,這些都是構建面向對象的基礎。可以通過function() {...}創建匿名函數(沒有函數名,也可賦給變量)。下面以例子來說明:

(function(){
var a = 10;
var b = 5;
alert(a * b);//返回50
})();//函數定義就立即執行

之所以能立即執行,是因為函數聲明后的一對括號。但我們發現,括號內空無一物,也並非完全如此。

(function(a, b){
alert(a * b);//返回50
})(10, 5);//與前面等價

這個匿名函數與前一個等價,只是變量沒有在函數內聲明,而是直接從外部傳入而已。其實,這個匿名函數也可以有個返回值,並賦給某個變量。

var c = (function(a, b){
return a * b;//返回50
})(10, 5);//與前面等價
alert(c);//50

匿名函數的最大用途是創建閉包。所謂閉包,就是一個受保護的變量空間,由內嵌函數生成。由於Javascript具有函數級的作用域,即定義在函數內部的變量在函數外部是不能被訪問的,函數僅運行在定義它的作用域中,而不是在調用的作用域中。這樣,就可以把變量包裹在匿名函數中加以保護。例如,你可以通過以下方式創建私有變量:

var c;
(function(){
var a = 10;
var b = 5;
c = function(){
return a * b;//返回50
}
})();
c();//c可以訪問a,b,即使它在匿名函數的外部也能被執行

4. Javascript對象是"易變"的。一切都是對象(除了3種基本類型),而且所有對象都是易變的。這意味着你能使用一些別的語言不存在的技術。例如為函數動態添加屬性。

function displayError(error){
displayError.numTimesExecuted++;
alert(error);
}
displayError.numTimesExecuted = 0;//意味着可對預先定義的類和對象進行修改

可以利用prototype機制在類的實例創建后再動態添加,此時對已定義的對象仍然有效。例如:

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);
//動態添加一個方法
Person.prototype.getGreeting = function() {
return "Hello " + this.getName() + "!";
};
//displayGreeting()僅對Miracle有效
miracle.displayGreeting = function() {
alert(this.getGreeting());
}

與對象的易變性相關的就是反射(也可稱為"內省"),即在運行時檢查對象的屬性和方法,並利用這些信息來實例化類和執行方法,甚至在開發時不需要知道它們的名稱。借助於對象的這兩大特性,可以完全模仿面向對象語言的高級特性,但要記住在Javascript中任何對象都是可以在運行時修改

5. Javascript具有實現"繼承"的天份。這里簡單提及一下:Javascript繼承包含"類式"繼承和基於對象的原型式繼承,這個話題我會在下一期的文章中詳細論述。

最后總結一下,之所以采用面向對象和設計模式的思想來處理Javascript這種看似過程式的語言,到底有什么好處呢?我總結了以下幾點供大家參考:

(1).可維護性。有助於降低模塊之間的耦合性,對項目中代碼可按模塊和功能職責來划分。

(2).便於交流。對於一個大型團隊來說,可能用設計模式很簡單的術語可以高度概括你所負責實現的功能模塊,而不必太多讓團隊其他成員關注過多的細節。

(3).提升性能。利用模式可以減少傳送到客戶端代碼量的同時並提高程序運行的速度。

當然,有利就有弊。弊端在於:

(1).復雜度相對較高。獲取可維護性的代價是以代碼的高度重構和模塊化的划分而成,對於一些新手來說,很難一下適應。

(2).部分模式反而降低性能。但是這種拖累依賴於你的項目需求,可能有時微不足道,有時難以接受。

因此,建議大家學會理解設計模式的應用場景,用對場景才是對設計模式的真正意義上的應用。盲目應用和用錯場景就是誤用,還不如不用


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM