【總結】富有表現力的JavaScript

JavaScript的靈活性

 JavaScript是目前最流行、應用最普遍的語言之一,它是一種極富表現力的語言,它具備C家族語言所罕見的特性。這種語言容許咱們使用各類方式來完成同一個任務或者功能,還容許咱們在面向對象編程的過程使用函數式編程中的概念來豐富其實現方式。這種語言容許咱們採用多種不一樣的編程風格進行編程,如簡單一些的函數式編程,複雜一些的面向對象編程。因此咱們能夠在長期的編碼過程當中,培養專門屬於本身的編程風格,下面的例子會體現出JavaScript的靈活性。html

下面咱們將要實現一個模擬開始播放音樂和中止播放音樂的小功能,代碼以下:編程

 1 /************************************************/
 2 //方法一:傳統的函數式編碼方式
 3 function start() {
 4     console.log("music start");
 5 }
 6 
 7 function stop() {
 8     console.log("music stop");
 9 }
10 
11 //頁面調用方法一
12 start();
13 stop();
14 /************************************************/
15 //方法二:利用prototype
16 var Player=function() {} //聲明function對象
17 
18 Player.prototype.start=function(){  //爲對象的prototype添加方法
19     console.log("music start by prototype");
20 }
21 Player.prototype.stop=function(){
22     console.log("music stop by prototype");
23 }
24 
25 //頁面調用方法二
26 Player =new Player();
27 Player.start();
28 Player.stop();
29 /************************************************/
30 //方法三:prototype進一步封裝
31 var ControlPlayer=function(){}
32 
33 ControlPlayer.prototype={
34     start:function () {
35         console.log("music start prototype-start");
36     },
37     stop:function(){
38         console.log("music stop prototype-stop");
39     }
40 }
41 
42 //頁面調用方法三
43 var c=new ControlPlayer();
44 c.start();
45 c.stop();
46 /************************************************/
47 //方法四:經過prototype添加方法,鏈式調用
48 Function.prototype.method=function(name,fn){ //注意function的大小寫,小寫會不識別句點
49     this.prototype[name]=fn;
50     return this;//鏈式調用
51 }
52 
53 ControlPlayer.method('start',function(){
54     console.log('music starting by chain... ...');
55 }).method('stop',function(){
56     console.log('music stopping by chain... ...');
57 });
58 
59 
60 //頁面調用方法四
61 ControlPlayer.prototype.start();
62 ControlPlayer.prototype.stop();
63 
64 /************************************************/
65 //方法五:經過prototype添加方法,非鏈式調用
66 Function.prototype.method=function(name,fn){ //注意function的大小寫,小寫會不識別句點
67     this.prototype[name]=fn;
68     //return this;//鏈式調用
69 }
70 
71 ControlPlayer.method('start',function(){
72     console.log('music starting... ...');
73 });
74 
75 ControlPlayer.method('stop',function(){
76     console.log('music stopping... ...');
77 });
78 
79 //頁面調用方法五,同四
80 ControlPlayer.prototype.start();
81 ControlPlayer.prototype.stop();

方法一很簡單,可是沒法建立能夠保存狀態而且具備一些僅僅對其內部狀態進行操做的方法的對象;方法二中將兩個方法(start、stop)賦給該類的prototype屬性;若是但願把類的定義封裝在一塊兒,能夠採用方法三的作法;方法四中使用Function.prototype.method爲該類添加新的方法,它有兩個參數,第一個是字符串型的方法名稱,第二個是具體的好函數;若是對方法四進行擴展,可讓它返回this,這樣就能夠進行鏈式調用,也就是方法五的內容。經過以上的幾個例子能夠發現,不使用prototype屬性定義的對象方法,是靜態的,只能用類名進行調用,另外此靜態方法中沒法使用this關鍵字來調用對象的其餘屬性;而使用prototype屬性定義的對象方法,是非靜態的,只有在實例化以後才能調用,其方法內部可使用this關鍵字來調用對象的其餘屬性;只有function才能被實例化,而Object則不能被實例化,前者能夠經過new操做符,然後者能夠經過賦值把對象保存在變量中並經過該變量對其內部成員進行訪問;若是是對象中的function,須要new一下這個function再使用。設計模式

弱類型語言

在Javascript中,聲明變量時能夠不指定類型,可是這不意味着變量沒有類型,變量的類型取決於變量的值。在Javascript中有5中原始類型,分別是Number、String、Boolean、Undefined和Null,此外還有對象類型Object和包含可執行代碼的函數類型,前者是一種複合數據類型(數組也是Object類型,它包含着一批有序的值集合)。原始類型按值傳遞,而其餘類型包括複合對象是按引用傳遞。Javascript中,能夠經過賦值來改變數據類型,原始數據類型之間也能夠進行轉換,toString方法能夠把Number和Boolean類型轉成字符串,parseFloat和parseInt能夠把字符變爲數值型,雙重非操做能夠把Number和String轉成Boolean類型。弱類型的變量帶來了極大的靈活性,Javascript會根據值進行自動轉換。數組

函數是一等對象

 在Javascript中,函數能夠存儲在變量中,能夠做爲參數傳給其餘函數,能夠做爲返回值從其餘函數傳出,還能夠在運行時進行構造,這些特性帶來了極大的靈活性和極強的表達能力,而這些正是構建傳統面向對象的框架基礎。下面的代碼建立了一個匿名函數並賦值給一個變量,代碼以下:網絡

 1 (function(){
 2     console.log('anonymous function!');
 3 })(); //此處括號表示當即調用,另外若是沒有分號,多個匿名函數時會報錯
 4 
 5 (function(){
 6     var a=20;
 7     var b=10;
 8     console.log(a*b);
 9 })();
10 
11 (function(a,b){
12     console.log(a*b);
13 })(12,13);//括號中傳入的參數和function中的形參一致,參數由外部傳入
14 
15 var result =(function(a,b){
16     return a*b;
17 })(3,3);
18 console.log(result);//result的值是匿名函數的返回值

匿名函數最有趣的用途是用於建立閉包(closure),閉包是一個受到保護的變量空間,由內嵌函數生成。Javascript具備函數級的做用域,這意味着在函數內部定義的變量在函數的外部是不能夠訪問的。Javascript的做用域是詞法性質,這意味着函數是運行在定義它的做用域中,而不是調用它的做用域中。把這兩個因素結合起來,就能夠經過把變量包裹在匿名函數中而對其加以保護,代碼以下:閉包

 1 var item;
 2 (function(){
 3     var a=12;
 4     var b=23;
 5     item=function(){
 6         return a*b;
 7     };
 8 })();
 9 
10 item();

變量a和b定義在匿名函數中,由於函數item定義在這個閉包中,因此它能訪問這兩個變量,即便是在該閉包結束後。架構

對象的易變性

在JavaScript中,一切都是對象,除了那幾種基本類型,即使是基本類型,在必要的時候也會被自動包裝爲對象,全部對象都是易變的(mutable),這意味着能夠在JavaScript中使用其餘語言不容許的技術。例如,爲函數添加屬性:框架

1 function displayError(msg) {
2     displayError.numTimesExcuted++;//新增屬性
3     alert(msg);
4 }
5 
6 displayError.numTimesExcuted=0;

這意味着能夠對先前的類或實例化的對象進行修改,代碼以下:函數式編程

 1 //定義Person類
 2 function Person(name,age){
 3     this.name=name;
 4     this.age=age;
 5 }
 6 //爲Person類添加GetName和GetAge方法
 7 Person.prototype={
 8     GetName:function(){
 9         return this.name;
10     },
11     GetAge:function(){
12         return this.age;
13     }
14 }
15 //新建一個Person類的實例tom
16 var tom=new Person('tom',21);
17 var name=tom.GetName();
18 console.log(name);
19 
20 //爲Person類添加Greeting方法
21 Person.prototype.Greeting=function(){
22     return 'hi,'+this.GetName();
23 }
24 //新建一個Person類的實例lucy
25 var lucy=new Person('lucy',23);
26 console.log(lucy.Greeting());
27 //爲tom實例添加displayGreeting方法
28 tom.displayGreeting=function(){
29     alert(this.Greeting());
30 }
31 tom.displayGreeting();

在這個例子中,Greeting方法是在建立Person類的兩個實例(tom、lucy)以後添加的,可是這兩個實例依然可以訪問到,這是由於prototype的工做機制。對象tom還獲得了displayGreeting方法,這是其餘實例所沒有的。與對象的易變性相關的還有一個內省(introspection)的概念,在運行時檢查對象所具備的屬性和方法,還可使用這種方法動態地建立類和執行其方法,這種技術稱之爲反射(reflection),大多數模仿傳統面向對象的特性的技術都是基於對象的易變性和反射。在JavaScript中,任何東西均可以在運行時動態地改變,固然也有不利的一面,由於咱們定義一個具備一套方法的類,到最後卻不能把保證它依舊無缺如初。函數

JavaScript的繼承

JavaScript中的繼承並不是傳統的面向對象的真正的繼承,而是基於prototype原型鏈的繼承方式,它能夠用來模擬傳統的基於類的繼承方式,可是性能略有差別,具體的使用還要看需求。

JavaScript中的設計模式

JavaScript的強大的表現力賦予了咱們在運用設計模式編寫代碼時極大的創造性,在JavaScript中使用設計模式主要有如下幾個緣由:

<1>可維護性:有助於下降模塊間的耦合性,使代碼重構和換用不一樣的模塊變得容易,使得代碼維護更加容易;

<2>溝通方便:設計模式爲處理不一樣類型的對象提供了一套通用的術語,這樣編碼人員在溝通時只要講明採用的設計模式便可清晰地表達,而沒必要涉足更細節層次的東西;

<3>提高性能:某些設計模式會大幅提高應用的性能,減小網絡傳輸,好比享元模式和代理模式,固然也有好多設計模式會下降性能,這個就須要使用者自行把握。

總結

JavaScript的豐富表現力是其力量之源,即便這種弱類型語言沒有本身的內置對象,可是咱們能夠隨時根據本身的需求進行擴展,因爲其實弱類型語言,因此定義變量時並不須要指定類型。函數是一等對象,而且能夠動態建立,所以能夠建立閉包;全部的對象都是易變的,能夠在運行時修改;可使用的繼承方式有兩種,一種是原型鏈繼承、另外一種是類式繼承,它們各有優缺點。JavaScript的設計模式並不是徹底有益,須要使用者根據具體的需求進行決策,使用不當甚至會產生負面的效果,過分複雜的架構會把應用程序拖入泥沼,因此要根據咱們本身的編碼風格選擇適合的模式來完成具體的工做。

 

 做者:悠揚的牧笛

 博客地址:http://www.cnblogs.com/xhb-bky-blog/p/5866675.html

 聲明:本博客原創文字只表明本人工做中在某一時間內總結的觀點或結論,與本人所在單位沒有直接利益關係。非商業,未受權貼子請以現狀保留,轉載時必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。

相關文章
相關標籤/搜索