《JavaScript語言精粹》內容精選

最近在讀《JavaScript語言精粹》這本書,做者是 Douglas CrockfordDouglas Crockford是一名來自 Yahoo!的資深JavaScript架構師,以建立和維護JSONJavaScript object notation)格式而爲你們所熟知。他會按期在各種會議上發表有關高級JavaScript的主題演講。他也是ESMAscript委員會的成員之一。
原本想寫一篇讀後感的,可是想一想,《JavaScript語言精粹》是我在JavaScript方面閱讀的第一本書,算是開拓視野,因此心中只有對這本書的總結,談不上有感。並且個人目的就是爲了節省閱讀這本書的時間,幫助你們瞭解大概的內容,我會盡可能把本身以爲其中的精髓傳達給想讀這本書的朋友。
注意:這本書不是給初學者的,也不是一本傻瓜式的教程。正則表達式

語法 Grammer

  1. JavaScript的兩種註釋形式:/**/(塊註釋)和 //(行註釋)編程

  2. 塊註釋的字符對可能出如今如今正則表達式的字面量裏,因此塊註釋相對來講不安全數組

    例如:
    /*
    var rm_a = /a*/.match(s);
        */
  3. 做者建議儘可能避免使用 /**/註釋,用 //來代替它。安全

標識符

  1. 標識符有一個字母開頭,其後能夠選擇性的加上一個或多個字母、數字或下劃線。閉包

  2. 標識符不能使用下面這些保留字:架構

abstract
boolean    break    byte
case    catch    char    class    const    continue
debugger    default    delete    do    double
else    enum    export    extends
false    final    finally    float    for    function
goto
if    implements    import    in    instanceof    int    interface
long
native    new    null
package    private    protected    public
return
short    static    super    switch    synchronized
this    throw    throws    transient    true    try    typeof
var    volatile    void
while    with

數字

  1. JavaScript只有一個數字類型。它在內部被表示與64位的浮點數,和Java的double數字類型同樣。app

  2. 若是一個數字字面量有指數部分,那麼這個字面量的值等於e以前的數字與10的e以後的數字的次方相乘。因此 100和 1e2是相同的數字。函數

  3. 數字擁有方法,JavaScript有一個對象Math,它包含一套用於數字的方法。
    例如,能夠用Math.floor(number)方法把一個數字轉換爲一個整數。工具

字符串

  1. JavaScript沒有字符類型。要表示一個字符,只需建立僅包含一個字符的字符串便可。開發工具

  2. 字符串有一個 length屬性。例如,"seven".length是5。

  3. 字符串也有一些方法。例如,'cat'.toUpperCase( ) === 'CAT'

語句

  1. 當 var語句被用於函數內部時,它定義的是這個函數的私有變量

  2. 語句一般是按照從上到下的順序被執行。JavaScript能夠經過條件語句(if和switch)、循環語句(while、for和do)、強制跳轉語句(break、return和throw)和函數調用來改變執行的序列

表達式

1. . [] ()    ----------提取屬性與調用函數
 2. * / %      ----------乘法、除法、求餘
 3. &&         ----------邏輯 與
 4.||          ----------邏輯 或
 5.?:        ----------三元

三元運算符?後面跟着另外一個表達式,而後接一個:,其後面接第三個表達式。
三元運算符?有三個運算數。若是第1個運算數的值爲真,產生第2個運算數的值;若是爲假,則產生第3個是運算數的值。

對象 Objects

JavaScript裏的對象是無類型的(class-free),對象能夠包含其餘對象。
JavaScript包含一種原型鏈的特徵,容許對象繼承另外一個對象的屬性。正確的使用它能減小對象初始化時消耗的時間和內存。
一、對象字面量 Object Literals

  • JavaScript的標識符中包含鏈接符「-」是不合法的,可是容許包含下劃線「_」,

  • 因此用引號括住「first-name」是必需的。

二、檢索 Retrieval

  • 要檢索對象裏包含的值,能夠採用[]後綴中括住一個字符串表達式的方式。

  • 若是字符串表達式是一個字符串字面量,那麼也能夠用 . 表示法代替。

  • 考慮優先使用 . 表示法,由於它更緊湊且可讀性更好。

  • 若是你嘗試檢索一個並不存在的成員屬性的值,將返回undefined

  • 嘗試從undefined的成員屬性中取值將會致使TypeError異常。這時能夠經過 && 運算符來避免錯誤。

三、原型 Prototype

  • 每一個對象都鏈接到一個原型對象,而且它能夠從中繼承屬性。全部經過對象字面量建立的對象都鏈接的Object.prototype,它是JavaScript中標配對象。

  • 當你建立一個新對象時,你能夠選擇某個對象做爲它的原型。JavaScript提供的實現機制雜亂而複雜,但其實能夠被明顯地簡化。咱們將給Object增長一個create方法。這個方法建立一個使用原對象做爲其原型的新對象。

if(typeof Object.beget !== 'function') {
    Object.create = function(o) {
        var F = function() {};
        F.prototype = o;
        return new F();
    };
}
var another_stooge = Object.create(stooge);
  • 原型鏈接在更新時是不起做用的。當咱們對某個對象作出的改變時,不會影響該對象的原型。

  • 若是咱們嘗試去獲取對象的某個屬性值,但該對象沒有此屬性名,那麼JavaScript會試着從原型對象中去獲取屬性值。若是那個原型對象也沒有改屬性,那麼再從它的原型中尋找,依此類推,直到最後到達終點Object.prototype

  • 若是想要的屬性徹底不存在原型鏈中,那麼結果就是undefined值。這個過程稱爲委託

  • 原型關係是一種動態關係。若是咱們添加一個新的屬性到原型中,該屬性會當即對全部基於該原型建立的對象可見。

四、反射 Reflection

  • 檢查對象並肯定對象有什麼屬性是很容易的事情,只要試着去檢索該屬性並驗證取得的值。Typeof 操做符對肯定屬性的類型有很大的幫助:

typeof flight.number            //'number'
typeof flight.status            //'string'
typeof flight.arrival           //'object'
typeof flight.manifest          //'undefined'
  • 注意任何原型鏈中的任何屬性都會產生值:

typeof flight.toString           //'function'
typeof flight.constructor        //'function'

有兩種方法處理掉這些不須要的屬性。第一個是讓你的程序作檢查並丟棄值爲函數的屬性。另外一個就是使用 hasOwnProperty 方法,若是對象有獨有的屬性,它將返回 true
hasOwnProperty方法不會檢查原型鏈。

fligth.hasOwnProperty('number')         //true
flight.hasOwnProperty('constructor')    //false

五、枚舉 Enumeration

  • for in 語句可用來遍歷一個對象中全部屬性名。改枚舉過程將會列出因此的屬性——包括函數和你可能不關心的原型中的屬性——因此不必過濾掉那些你不想要的值。最爲經常使用的過濾器是 hasOwnProperty 方法,以及使用 typeof 來排除函數:

var name;
for(name in another_stooge) {
    if(typeof another_stooge[name] !== 'function') {
        document.writeln(name + ':' + another_stooge[name]);
    }
}
  • 屬性名出現的順序是不肯定的,所以要對任何可能出現的順序有所準備。若是你想要確保屬性以特定的順序出現,最後的辦法是徹底避免使用 for in 語句,而是建立一個數組,在其中以正確的順序包含屬性名:

var i;
var propertier = {
    'fiirst-name',
    'middle-name',
    'last-name',
    'profession'
};
for(i = 0; i< properties.length; i += 1) {
    document.writeln(properties[i] + ':' + another_stooge[properties[i]]);
}

經過 for 而不是 for in,能夠獲得咱們想要的屬性,而不用擔憂可能發掘出原型鏈中的屬性,而且咱們按正確的順序取得了它們的值。

六、刪除 Delete

  • delete運算符能夠用來刪除對象的屬性。若是對象包含該屬性,那麼該屬性就會被移除。它不會觸及原型鏈中的任何對象。

  • 刪除對象的屬性可能會讓來自原型鏈中的屬性透現出來:

another_stooge.nickname            //'Moe'
delete another_stooge.nickname;
another_stooge.nickname            //'Curly'

七、減小全局變量污染 Global Abatement

  • 全局變量削弱了程序的靈活性,應該避免使用。

  • 最小化使用全局變量的方法之一是爲你的應用值建立一個惟一的全局變量:

var MYAPP = {};

該變量此時變成了你的應用的容器:

MYAPP.stooge = {
    "first-name": "joe",
    "last-name": "Howard"
};
MYAPP.flight = {
    airline: "Oceanic",
    departure: {
        IATA: "SYD",
        city: "Sydney"
    }
};
  • 只要把全局性的資源都歸入一個名稱空間下,你的這個程序與其餘應用程序、組件或類庫之間發生衝突的可能性就會顯著下降。這個程序也會變得更容易閱讀,由於很明顯,MYAPP.stooge 指向的是頂層結構。還有一種有效減小全局污染的方法,隱藏信息的方法,就是 閉包

函數 Functions

一、函數字面量 Function Literal

  • 函數對象經過函數字面量來建立:

//建立一個名爲 add 的變量,並用來把兩個數字相加的函數賦值給它
var add = function(a,b) {
    return a + b;
};

函數字面量包括4個部分。

  • 第1個部分是保留字 function

  • 第2個部分是函數名,它能夠被省略。函數能夠用它的名字遞歸地調用本身。此名字也可能被調試器和開發工具用來識別函數。若是沒有給函數命名,則它被成爲匿名函數(anonymous)

  • 第3個部分是包圍在圓括號中的一組參數。多個參數用逗號隔開。這些參數的名稱被定義爲函數中的變量。它們不像普通的變量那樣被初始化爲 undefined,而是在該函數被調用時初始化爲實際提供的參數的值。

  • 第4個部分是包圍在花括號中的一組語句。這些語句是函數的主體,它們在函數被調用是執行。

  • 函數字面量能夠出如今任何容許表達式出現的地方。一個內部函數除了能夠訪問本身的參數和變量,同時它也能自由訪問把它嵌套在其中的父函數的參數和變量。經過函數字面量建立的函數對象包含一個連到外部上下文的鏈接。這被稱爲 閉包(closure)。它是JavaScript強大表現力的來源!

二、調用 Invocation
調用一個函數會暫停當前函數的執行,傳遞控制權和參數給新函數。除了聲明時定義的形式參數,每一個參數還接手兩個附加的參數:thisarguments。參數 this 在面向對象編程中很是重要,它的值取決於調用的模式。在JavaScript中一共有4種調用模式:方法調用模式、函數調用模式、構造器調用模式和 apply 調用模式。這些模式在若是初始化關鍵參數 this 上存在差別。
調用運算符是跟任何產生一個函數值的表達式後的一對圓括號。圓括號中內可包含0個或多個用逗號隔開的表達式。每一個表達式產生一個參數值。每一個參數值被賦予函數聲明時定義的形式參數名。當實際參數(arguments)和形式參數(parameters)的個數不匹配時,不會致使運行時的錯誤。若是實際參數值過多了,超出的參數值會被忽略。若是實際參數值過少,缺失的值被替換爲 undefined 。對參數值不會進行類型檢查:任何類型的值均可以被傳遞給任何參數。

  • 方法調用模式 The Method Invocation Pattern
    當一個函數被保存爲對象的一個屬性是,咱們稱它爲一個方法。當一個方法被調用時, this 被綁定到該對象。若是調用表達式包含一個提取屬性的動做(即包含一個 . 點符號的表達式[subscript]下標表達式),那麼它就是被當作一個方法來調用。

var myObject = {
  value :0;
  increment:function(inc){
    this.value += typeof inc ==='number'?inc:1;
  }   / /increment方法接受一個可選的參數,若是參數不是數字,默認使用數字1.  
};  
myObject.increment();
document.writeln(myObject.value);   // 1 

myObject.increment(2);  
document.writeln(myObject.value);   // 3

方法可使用 this 去訪問對象,能從對象中修改該對象。this 到對象的每綁定發生在調用的時候,這個超級遲綁定使用函數能夠對 this 高度複用。經過 this 可取得它們所屬對象的上下文的方法稱爲公共方法

  • 函數調用模式 The Function Invocation Pattern

當函數並不是對象的屬性時,它被看成一個函數來調用:

var sum = add(3, 4);          //sum的值爲7

當函數以此模式調用時,this 被綁定到全局對象,這是語言設計上的一個錯誤。當內部函數被調用時,this 應該綁定到外部函數的 this 變量。解決方案是:若是該方法定義一個變量並給它賦值爲 this ,那麼內部函數就能夠經過那個變量訪問到 this,按照約定,命名爲 that

myObject.double = function () {   // 給myObject增長一個double方法
  var that = this;             // 解決方法
  var helper = function() {
   that.value = add(that.value, that.value);  
  };
  helper();                     // 以函數的形式調用helper
};  
myObject.double();            // 以方法的形式調用double
document.writeln(myObject.Value());  //6
  • 構造器調用模式 The Constructor Invocation Pattern

JavaScript是基於原型繼承的語言,意味着對象能夠直接從其它對象繼承屬性,該語言是無類別的。
若是在一個函數前面帶上new來調用,將建立一個隱藏鏈接到該函數的prototype成員的新對象,同時this將會被綁定到那個新對象上。new前綴也會改變return語句的行爲。

var Quo = function (string){       //建立構造器函數Quo,有status屬性的對象
    this.status = string;
};
Quo.prototype.get_status = function() { //提供一個名爲get_status的公共方法
    return this.status;  
};  
var myQuo = new Quo("confused");   //構造一個Quo實例
document.wirteln(myQuo.get_status());     //打印顯示「confused」
相關文章
相關標籤/搜索