ECMAScript5.1及其新增API簡介

風靈使發表於2018-10-25

以前一種對ECMAScript的概念比較模糊,以及它跟JavascriptJscript等指令碼語言之間的關係不是太明白。本篇文章將就這些問題展示敘述。

什麼是ECMAScript

業界所說的ECMAScript其實是指一種規範,或者說是一個標準。具體點來說,它其實就是一份文件。其官網地址是http://www.ecmascript.org/。而我們通過所說的ECMAScript標準具體是指ECMA-262這份官方文件。

目前ECMAScript釋出的最新版本是Fifth Edition of ECMA-262,不過本篇文章我們將暫時不會講ES6的相關東西。

這裡有一份ES5的中文資料,可以認為其實官方文件的翻譯版。

標準的實現

前面我們知道ECMAScript其實就是一份標準文件,有ECMA標準化組織的TC39委員會制定的。但是這個組織只負責制定標準並不負責實現標準。那麼是誰來實現這份標準呢?回答是各大瀏覽器廠商。

目前市面上常見的實現ECMAScript標準的指令碼語言包括JavascriptJscript等。同時這些標準實現由於一些歷史原因和客觀原因,各個版本之間、各個瀏覽器廠商的實現有一些差異,甚至是很大的差異。

關於ECMAScriptJavascriptJscript這三者之間的關係,可以參閱三國志的故事(ECMAScriptJavaScriptJScript)。

ECMAScript 5.1

ECMAScript 5.1就是我們常說的es5。它在2012年就已經被公開。時至今日,除了一些較低版本的瀏覽器,各大主流瀏覽器都已經實現支援了es5的絕大部分特性。

這裡有一份不錯的關於es5的文件,並附帶了許多有價值的註釋,有興趣可移步Annotated ECMAScript 5.1

瀏覽器支援

一般來說,除了針對個別特性的特殊說明,各大主流瀏覽器都支援es5,包括

    Chrome 13+
    Firefox 4+
    Safari 5.1*
    IE 9*

其中IE9不支援es的嚴格模式,從IE10開始支援。Safari 5.1不支援Function.prototype.bind

ES5新特性簡介

下面我們將會針對ES5新增的特性或者API作一些簡要介紹。不過不會非常具體的講解,因為可能部分新增特性的講解可能都需要一篇文章的篇幅來描述。

Strict Mode

Strict Mode, 即所謂的嚴格模式。嚴格模式的意義是為了提供一種更佳良好錯誤檢查機制,讓你規避掉一些語言本身的bad point

比如在嚴格模式下,我們不可以使用一個未經宣告的變數。看下面的示例程式碼,

"use strict"
function foo() {
    var testVar = 4;
    return testVar;
}
// This causes a syntax error.
testVar = 5;

上面的示例程式碼中,我們試圖對一個未定義的變數進行賦值操作。在一般情況下(非嚴格模式)Javascript的執行引擎會認為這個testVar是一個全域性變數,這一隱式轉換在某些時候將會帶來各種bug。而在嚴格模式下,你將會直接得到一個語法錯誤提示。

開啟嚴格模式的方法很簡單,只需要在檔案的頂部寫上字串use strict即可。當然這需要執行環境支援嚴格模式。另外由於use strict其實是一個字串常量。那麼即使遇到不支援嚴格模式的環境,這行字串只會被安全的忽略,不會帶來任何的問題。

關於嚴格模式的更多內容,可移步閱讀這篇文章Strict Mode (JavaScript)

JSON物件

ES5提供一個內建的(全域性)JSON物件,可用來序列化(JSON.stringfy)和反序列化(parse)物件為JSON格式。其一般性用法如下,

var test = {
    "name": "gejiawen",
    "age": 22
};
console.log(JSON.strinfy(test)); // '{"name": "gejiawen", "age": 22}'
console.log(JSON.parse('{"name": "larry"}')); // Object {name: "larry"}

JSON物件提供的parse方法還提供第二個引數,用於對具體的反序列化操作做處理。比如,

JSON.parse('{"name": "gejiawen", "age": 22, "lucky": "13"}', function(key, value) {
    return typeof value === 'string' ? parseInt(value) : value;
});

這裡我們在回撥函式中對解析的每一對鍵值對作處理,如果其是一個數字字串,我們則對其進行parseInt操作,確保返回的value必定是數值型的。

JSON物件提供的stringify方法也會提供第二個引數,用於解析的預處理,同時也會提供第三個引數,用於格式化json字串。比如,

var o = {
    name: 'gejiawen',
    age: 22,
    lucky: '13'    
};
var ret = JSON.stringify(o, function(key, value) {
    return typeof value === 'string' ? undefined : value;
}, 4);
console.log(ret);

上面程式碼在輸出時,得到的字串將不會再呈現一行輸出,而是正常的格式化輸出,並採用4個space進行格式化。

另外,如果預處理函式的返回值為undefined,則此鍵值對將不會包含在最終的JSON字串中。所以上面程式碼最終的結果是,

"{
    "age": 22
}"

新增Object介面

物件 構造器 說明
Object getPrototypeOf 返回物件的原型
Object getOwnPropertyDescriptor 返回物件自有屬性的屬性描述符
Object getOwnPropertyNames 返回一個陣列,包括物件所有自有屬性名稱集合(包括不可列舉的屬性)
Object create 建立一個擁有置頂原型和若干個指定屬性的物件
Object defineProperty 給物件定義一個新屬性,或者修改已有的屬性,並返回
Object defineProperties 在一個物件上新增或修改一個或者多個自有屬性,並返回該物件
Object seal 鎖定物件。阻止修改現有屬性的特性,並阻止新增新屬性。但是可以修改已有屬性的值。
Object freeze 凍結物件,阻止對物件的一切操作。凍結物件將永遠不可變。
Object preventExtensions 讓一個物件變的不可擴充套件,也就是永遠不能再新增新的屬性。
Object isSealed 判斷物件是否被鎖定
Object isFrozen 判斷物件是否被凍結
Object isExtensible 判斷物件是否可以被擴充套件
Object keys 返回一個由給定物件的所有可列舉自身屬性的屬性名組成的陣列

這裡不打算對每個新增介面作詳細描述,不過比較常用的有如下幾個,

  • Object.create
  • Object.defineProperties
  • Object.keys

更多具體的用法請參閱Mozilla開發者文件。

新增Array介面

物件 構造器 說明
Array.prototype indexOf 返回根據給定元素找到的第一個索引值,否則返回-1
Array.prototype lastIndexOf 方法返回指定元素在陣列中的最後一個的索引,如果不存在則返回 -1
Array.prototype every 測試陣列的所有元素是否都通過了指定函式的測試
Array.prototype some 測試陣列中的某些元素是否通過了指定函式的測試
Array.prototype forEach 讓陣列的每一項都執行一次給定的函式
Array.prototype map 返回一個由原陣列中的每個元素呼叫一個指定方法後的返回值組成的新陣列
Array.prototype filter 利用所有通過指定函式測試的元素建立一個新的陣列,並返回
Array.prototype reduce 接收一個函式作為累加器,陣列中的每個值(從左到右)開始縮減,最終為一個值
Array.prototype reduceRight 接受一個函式作為累加器,讓每個值(從右到左,亦即從尾到頭)縮減為一個值

新增的陣列介面中,基本都是比較有用的介面。需要注意的一點是,有的陣列方法是不返回新陣列的,有的介面是返回一個新陣列,就是說使用這些新介面時,需要注意一下方法的返回值。

另外Array還有一個新增的介面,Array.isArray。顯然此新增介面並不是例項方案,而是類似“靜態方法”一樣的存在。其作用很簡單,就是判斷某一物件是否為陣列。

更多具體的用法請參閱Mozilla開發者文件。

Function.prototype.bind

bind()方法會建立一個新函式,稱為繫結函式.當呼叫這個繫結函式時,繫結函式會以建立它時傳入 bind()方法的第一個引數作為 this,傳入 bind() 方法的第二個以及以後的引數加上繫結函式執行時本身的引數按照順序作為原函式的引數來呼叫原函式。

此方法的用法如下,

fun.bind(thisArg[, arg1[, arg2[, ...]]])

使用bind可以為函式自定義this指標。它的常見使用場景如下,

this.x = 9; 
var module = {
    x: 81,
    getX: function() {
        return this.x;
    }
};
module.getX(); // 81
var getX = module.getX;
getX(); // 9, 因為在這個例子中,"this"指向全域性物件
// 建立一個'this'繫結到module的函式
var boundGetX = getX.bind(module);
boundGetX(); // 81

Javascript中重新繫結this變數的語法糖還有callapply。不過bind顯然與它們有著明顯的不同。bind將會返回一個新的函式,而call或者apply並不會返回一個新的函式,它們將會使用新的this指標直接進行函式呼叫。

相關文章