以前一種對(duì)ECMAScript的概念比較模糊,以及它跟Javascript、Jscript等腳本語言之間的關(guān)系不是太明白。本篇文章將就這些問題展示敘述。
業(yè)界所說的ECMAScript其實(shí)是指一種規(guī)范,或者說是一個(gè)標(biāo)準(zhǔn)。具體點(diǎn)來說,它其實(shí)就是一份文檔。其官網(wǎng)地址是http://www.ecmascript.org/。而我們通過所說的ECMAScript標(biāo)準(zhǔn)具體是指ECMA-262這份官方文檔。
目前ECMAScript釋出的最新版本是Fifth Edition of ECMA-262,不過本篇文章我們將暫時(shí)不會(huì)講ES6的相關(guān)東西。
這里有一份ES5的中文資料,可以認(rèn)為其實(shí)官方文檔的翻譯版。
前面我們知道ECMAScript其實(shí)就是一份標(biāo)準(zhǔn)文檔,有ECMA標(biāo)準(zhǔn)化組織的TC39委員會(huì)制定的。但是這個(gè)組織只負(fù)責(zé)制定標(biāo)準(zhǔn)并不負(fù)責(zé)實(shí)現(xiàn)標(biāo)準(zhǔn)。那么是誰來實(shí)現(xiàn)這份標(biāo)準(zhǔn)呢?回答是各大瀏覽器廠商。
目前市面上常見的實(shí)現(xiàn)ECMAScript標(biāo)準(zhǔn)的腳本語言包括Javascript、Jscript等。同時(shí)這些標(biāo)準(zhǔn)實(shí)現(xiàn)由于一些歷史原因和客觀原因,各個(gè)版本之間、各個(gè)瀏覽器廠商的實(shí)現(xiàn)有一些差異,甚至是很大的差異。
關(guān)于ECMAScript、Javascript、Jscript這三者之間的關(guān)系,可以參閱三國志的故事(ECMAScript、JavaScript和JScript)。
ECMAScript 5.1就是我們常說的es5。它在2012年就已經(jīng)被公開。時(shí)至今日,除了一些較低版本的瀏覽器,各大主流瀏覽器都已經(jīng)實(shí)現(xiàn)支持了es5的絕大部分特性。
這里有一份不錯(cuò)的關(guān)于es5的文檔,并附帶了許多有價(jià)值的注釋,有興趣可移步Annotated ECMAScript 5.1。
一般來說,除了針對(duì)個(gè)別特性的特殊說明,各大主流瀏覽器都支持es5,包括
其中IE9不支持es的嚴(yán)格模式,從IE10開始支持。Safari 5.1不支持Function.prototype.bind
。
下面我們將會(huì)針對(duì)ES5新增的特性或者API作一些簡要介紹。不過不會(huì)非常具體的講解,因?yàn)榭赡懿糠中略鎏匦缘闹v解可能都需要一篇文章的篇幅來描述。
Strict Mode, 即所謂的嚴(yán)格模式。嚴(yán)格模式的意義是為了提供一種更佳良好錯(cuò)誤檢查機(jī)制,讓你規(guī)避掉一些語言本身的bad point。
比如在嚴(yán)格模式下,我們不可以使用一個(gè)未經(jīng)聲明的變量??聪旅娴氖纠a,
"use strict"
function foo() {
var testVar = 4;
return testVar;
}
// This causes a syntax error.
testVar = 5;
上面的示例代碼中,我們?cè)噲D對(duì)一個(gè)未定義的變量進(jìn)行賦值操作。在一般情況下(非嚴(yán)格模式)Javascript的執(zhí)行引擎會(huì)認(rèn)為這個(gè)testVar
是一個(gè)全局變量,這一隱式轉(zhuǎn)換在某些時(shí)候?qū)?huì)帶來各種bug。而在嚴(yán)格模式下,你將會(huì)直接得到一個(gè)語法錯(cuò)誤提示。
開啟嚴(yán)格模式的方法很簡單,只需要在文件的頂部寫上字符串use strict
即可。當(dāng)然這需要執(zhí)行環(huán)境支持嚴(yán)格模式。另外由于use strict
其實(shí)是一個(gè)字符串常量。那么即使遇到不支持嚴(yán)格模式的環(huán)境,這行字符串只會(huì)被安全的忽略,不會(huì)帶來任何的問題。
關(guān)于嚴(yán)格模式的更多內(nèi)容,可移步閱讀這篇文章Strict Mode (JavaScript)。
ES5提供一個(gè)內(nèi)置的(全局)JSON對(duì)象,可用來序列化(JSON.stringfy
)和反序列化(parse
)對(duì)象為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對(duì)象提供的parse
方法還提供第二個(gè)參數(shù),用于對(duì)具體的反序列化操作做處理。比如,
JSON.parse('{"name": "gejiawen", "age": 22, "lucky": "13"}', function(key, value) {
return typeof value === 'string' ? parseInt(value) : value;
});
這里我們?cè)诨卣{(diào)函數(shù)中對(duì)解析的每一對(duì)鍵值對(duì)作處理,如果其是一個(gè)數(shù)字字符串,我們則對(duì)其進(jìn)行parseInt
操作,確保返回的value
必定是數(shù)值型的。
JSON對(duì)象提供的stringify
方法也會(huì)提供第二個(gè)參數(shù),用于解析的預(yù)處理,同時(shí)也會(huì)提供第三個(gè)參數(shù),用于格式化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);
上面代碼在輸出時(shí),得到的字符串將不會(huì)再呈現(xiàn)一行輸出,而是正常的格式化輸出,并采用4個(gè)space進(jìn)行格式化。
另外,如果預(yù)處理函數(shù)的返回值為undefined
,則此鍵值對(duì)將不會(huì)包含在最終的JSON字符串中。所以上面代碼最終的結(jié)果是,
"{
"age": 22
}"
Object
接口對(duì)象 | 構(gòu)造器 | 說明 |
---|---|---|
Object |
getPrototypeOf |
返回對(duì)象的原型 |
Object |
getOwnPropertyDescriptor |
返回對(duì)象自有屬性的屬性描述符 |
Object |
getOwnPropertyNames |
返回一個(gè)數(shù)組,包括對(duì)象所有自有屬性名稱集合(包括不可枚舉的屬性) |
Object |
create |
創(chuàng)建一個(gè)擁有置頂原型和若干個(gè)指定屬性的對(duì)象 |
Object |
defineProperty |
給對(duì)象定義一個(gè)新屬性,或者修改已有的屬性,并返回 |
Object |
defineProperties |
在一個(gè)對(duì)象上添加或修改一個(gè)或者多個(gè)自有屬性,并返回該對(duì)象 |
Object |
seal |
鎖定對(duì)象。阻止修改現(xiàn)有屬性的特性,并阻止添加新屬性。但是可以修改已有屬性的值。 |
Object |
freeze |
凍結(jié)對(duì)象,阻止對(duì)對(duì)象的一切操作。凍結(jié)對(duì)象將永遠(yuǎn)不可變。 |
Object |
preventExtensions |
讓一個(gè)對(duì)象變的不可擴(kuò)展,也就是永遠(yuǎn)不能再添加新的屬性。 |
Object |
isSealed |
判斷對(duì)象是否被鎖定 |
Object |
isFrozen |
判斷對(duì)象是否被凍結(jié) |
Object |
isExtensible |
判斷對(duì)象是否可以被擴(kuò)展 |
Object |
keys |
返回一個(gè)由給定對(duì)象的所有可枚舉自身屬性的屬性名組成的數(shù)組 |
這里不打算對(duì)每個(gè)新增接口作詳細(xì)描述,不過比較常用的有如下幾個(gè),
Object.create
Object.defineProperties
Object.keys
更多具體的用法請(qǐng)參閱Mozilla開發(fā)者文檔。
Array
接口對(duì)象 | 構(gòu)造器 | 說明 |
---|---|---|
Array.prototype |
indexOf |
返回根據(jù)給定元素找到的第一個(gè)索引值,否則返回-1 |
Array.prototype |
lastIndexOf |
方法返回指定元素在數(shù)組中的最后一個(gè)的索引,如果不存在則返回 -1 |
Array.prototype |
every |
測試數(shù)組的所有元素是否都通過了指定函數(shù)的測試 |
Array.prototype |
some |
測試數(shù)組中的某些元素是否通過了指定函數(shù)的測試 |
Array.prototype |
forEach |
讓數(shù)組的每一項(xiàng)都執(zhí)行一次給定的函數(shù) |
Array.prototype |
map |
返回一個(gè)由原數(shù)組中的每個(gè)元素調(diào)用一個(gè)指定方法后的返回值組成的新數(shù)組 |
Array.prototype |
filter |
利用所有通過指定函數(shù)測試的元素創(chuàng)建一個(gè)新的數(shù)組,并返回 |
Array.prototype |
reduce |
接收一個(gè)函數(shù)作為累加器,數(shù)組中的每個(gè)值(從左到右)開始縮減,最終為一個(gè)值 |
Array.prototype |
reduceRight |
接受一個(gè)函數(shù)作為累加器,讓每個(gè)值(從右到左,亦即從尾到頭)縮減為一個(gè)值 |
新增的數(shù)組接口中,基本都是比較有用的接口。需要注意的一點(diǎn)是,有的數(shù)組方法是不返回新數(shù)組的,有的接口是返回一個(gè)新數(shù)組,就是說使用這些新接口時(shí),需要注意一下方法的返回值。
另外Array
還有一個(gè)新增的接口,Array.isArray
。顯然此新增接口并不是實(shí)例方案,而是類似“靜態(tài)方法”一樣的存在。其作用很簡單,就是判斷某一對(duì)象是否為數(shù)組。
更多具體的用法請(qǐng)參閱Mozilla開發(fā)者文檔。
Function.prototype.bind
bind()方法會(huì)創(chuàng)建一個(gè)新函數(shù),稱為綁定函數(shù).當(dāng)調(diào)用這個(gè)綁定函數(shù)時(shí),綁定函數(shù)會(huì)以創(chuàng)建它時(shí)傳入 bind()方法的第一個(gè)參數(shù)作為 this,傳入 bind() 方法的第二個(gè)以及以后的參數(shù)加上綁定函數(shù)運(yùn)行時(shí)本身的參數(shù)按照順序作為原函數(shù)的參數(shù)來調(diào)用原函數(shù)。
此方法的用法如下,
fun.bind(thisArg[, arg1[, arg2[, ...]]])
使用bind
可以為函數(shù)自定義this
指針。它的常見使用場景如下,
this.x = 9;
var module = {
x: 81,
getX: function() {
return this.x;
}
};
module.getX(); // 81
var getX = module.getX;
getX(); // 9, 因?yàn)樵谶@個(gè)例子中,"this"指向全局對(duì)象
// 創(chuàng)建一個(gè)'this'綁定到module的函數(shù)
var boundGetX = getX.bind(module);
boundGetX(); // 81
Javascript中重新綁定this
變量的語法糖還有call
和apply
。不過bind
顯然與它們有著明顯的不同。bind
將會(huì)返回一個(gè)新的函數(shù),而call
或者apply
并不會(huì)返回一個(gè)新的函數(shù),它們將會(huì)使用新的this
指針直接進(jìn)行函數(shù)調(diào)用。
更多建議: