ecmascript的特性有:1、class(類);2、模組化;3、箭頭函數;4、模板字串;5、解構賦值;6、延展操作符;7、Promise;8、let與const;9、指數操作符「**」;10、「async/await」等等。
本教學操作環境:windows7系統、javascript1.8.5版、Dell G3電腦。
ECMAScript 是一種由 ECMA國際(前身為歐洲計算機制造商協會)通過 ECMA-262 標準化的指令碼程式設計語言。
Ecma國際(Ecma International)是一家國際性會員制度的資訊和電信標準組織。1994年之前,名為歐洲計算機制造商協會(European Computer Manufacturers Association)。因為計算機的國際化,組織的標準牽涉到很多其他國家,因此組織決定改名錶明其國際性。現名稱已不屬於首字母縮略字。
與國家政府標準機構不同,Ecma國際是企業會員制的組織。組織的標準化過程比較商業化,自稱這種營運方式減少官僚追求效果。
其實 Ecma國際負責了很多標準的制定,比如有如下這些規範。大家可以看到這裡面有我們今天的主角,ECMAScript 規範、 C#語言規範、 C++/CLI語言規範等。
1996 年 11 月,JavaScript 的創造者 Netscape 公司,決定將 JavaScript 提交給標準化組織 ECMA,希望這種語言能夠成為國際標準。次年,ECMA 釋出 262 號標準檔案(ECMA-262)的第一版,規定了瀏覽器指令碼語言的標準,並將這種語言稱為 ECMAScript,這個版本就是 1.0 版。
該標準從一開始就是針對 JavaScript 語言制定的,但是之所以不叫 JavaScript,有兩個原因。一是商標,Java 是 Sun 公司的商標,根據授權協定,只有 Netscape 公司可以合法地使用 JavaScript 這個名字,且 JavaScript 本身也已經被 Netscape 公司註冊為商標。二是想體現這門語言的制定者是 ECMA,不是 Netscape,這樣有利於保證這門語言的開放性和中立性。
因此,ECMAScript 和 JavaScript 的關係是,前者是後者的規格,後者是前者的一種實現。
ECMAScript 2015(簡稱 ES2015)這個詞,也是經常可以看到的。它與 ES6 是什麼關係呢?
2011 年,ECMAScript 5.1 版釋出後,就開始制定 6.0 版了。因此,ES6 這個詞的原意,就是指 JavaScript 語言的下一個版本。
但是,因為這個版本引入的語法功能太多,而且制定過程當中,還有很多組織和個人不斷提交新功能。事情很快就變得清楚了,不可能在一個版本里麵包括所有將要引入的功能。常規的做法是先發布 6.0 版,過一段時間再發 6.1 版,然後是 6.2 版、6.3 版等等。
標準委員會最終決定,標準在每年的 6 月份正式釋出一次,作為當年的正式版本。接下來的時間,就在這個版本的基礎上做改動,直到下一年的 6 月份,草案就自然變成了新一年的版本。這樣一來,就不需要以前的版本號了,只要用年份標記就可以了。
因此,ES6 既是一個歷史名詞,也是一個泛指,含義是 5.1 版以後的 JavaScript 的下一代標準,涵蓋了 ES2015、ES2016、ES2017 等等,而 ES2015 則是正式名稱,特指該年釋出的正式版本的語言標準。
1996年11月,Netscape公司將Js提交給國際化標準組織ECMA,當初該語言能夠成為國際化標準。
1997年,ECMAScript 1.0版本推出。(在這年,ECMA釋出262號標準檔案(ECMA-262)的第一版,規定瀏覽器指令碼語言的標準,並將這種語言稱為ECMAScript,也就是ES1.0版本。)
1998年6月,ES 2.0 版釋出。
1999年12月,ES 3.0 版釋出,併成為JS的通行標準,得到廣泛支援。
2007年10月,ES 4.0 版草案發布。
2008年7月,由於各方分歧太大,ECMA決定終止ES 4.0的開發。轉而將其中涉及現有功能改善的一小部分發布為ES 3.1 。但是回後不久將其改名為ES 5.0版;
2009年12月,ES 5.0 版正式釋出。
2011年6月,ES 5.1 版釋出,併成為ISO國際標準(ISO/IEC 16262:2011)。
2013年3月,ES 6 草案終結,並且不再新增新的功能。
2013年12月,ES 6 草案發布。
2015年6月,ES 6 正式版本釋出。
從此後面每年6月都會發佈一個正式版本,所以目前最新的版本是2021年6月釋出的ES12。
1、class
ES6 引入了 class(類),讓 JavaScript 的物件導向程式設計變得更加簡單和易於理解。
class Student { constructor() { console.log("I'm a student."); } study() { console.log('study!'); } static read() { console.log("Reading Now."); } } console.log(typeof Student); // function let stu = new Student(); // "I'm a student." stu.study(); // "study!" stu.read(); // "Reading Now."
2、模組化
ES5 支援原生的模組化,在ES6中模組作為重要的組成部分被新增進來。模組的功能主要由 export 和 import 組成。每一個模組都有自己單獨的作用域,模組之間的相互呼叫關係是通過 export 來規定模組對外暴露的介面,通過 import 來參照其它模組提供的介面。同時還為模組創造了名稱空間,防止函數的命名衝突。
export function sum(x, y) { return x + y; } export var pi = 3.141593;
import * as math from "lib/math"; alert("2π = " + math.sum(math.pi, math.pi)); import {sum, pi} from "lib/math"; alert("2π = " + sum(pi, pi));
3、箭頭函數
=>不只是關鍵字 function 的簡寫,它還帶來了其它好處。箭頭函數與包圍它的程式碼共用同一個 this,能幫你很好的解決this的指向問題。比如 var self = this;或 var that =this這種參照外圍this的模式。但藉助 =>,就不需要這種模式了。
() => 1 v => v+1 (a,b) => a+b () => { alert("foo"); } e => { if (e == 0){ return 0; } return 1000/e; }
4、模板字串
ES6 支援 模板字串,使得字串的拼接更加的簡潔、直觀。
//不使用模板字串 var name = 'Your name is ' + first + ' ' + last + '.' //使用模板字串 var name = `Your name is ${first} ${last}.`
在 ES6 中通過 ${}
就可以完成字串的拼接,只需要將變數放在大括號之中。
5、解構賦值
解構賦值語法是 JavaScript 的一種表示式,可以方便的從陣列或者物件中快速提取值賦給定義的變數。
// 物件 const student = { name: 'Sam', age: 22, sex: '男' } // 陣列 // const student = ['Sam', 22, '男']; // ES5; const name = student.name; const age = student.age; const sex = student.sex; console.log(name + ' --- ' + age + ' --- ' + sex); // ES6 const { name, age, sex } = student; console.log(name + ' --- ' + age + ' --- ' + sex);
6、延展操作符
延展操作符…可以在函數呼叫/陣列構造時, 將陣列表示式或者 string 在語法層面展開;還可以在構造物件時, 將物件表示式按 key-value 的方式展開。
//在函數呼叫時使用延展操作符 function sum(x, y, z) { return x + y + z } const numbers = [1, 2, 3] console.log(sum(...numbers)) //陣列 const stuendts = ['Jine', 'Tom'] const persons = ['Tony', ...stuendts, 'Aaron', 'Anna'] conslog.log(persions)
7、Promise
Promise 是非同步程式設計的一種解決方案,比傳統的解決方案 callback 更加的優雅。它最早由社群提出和實現的,ES6 將其寫進了語言標準,統一了用法,原生提供了 Promise 物件。
const getJSON = function(url) { const promise = new Promise(function(resolve, reject){ const handler = function() { if (this.readyState !== 4) { return; } if (this.status === 200) { resolve(this.response); } else { reject(new Error(this.statusText)); } }; const client = new XMLHttpRequest(); client.open("GET", url); client.onreadystatechange = handler; client.responseType = "json"; client.setRequestHeader("Accept", "application/json"); client.send(); }); return promise; }; getJSON("/posts.json").then(function(json) { console.log('Contents: ' + json); }, function(error) { console.error('出錯了', error); });
8、let 與 const
在之前 JS 是沒有塊級作用域的,const與 let 填補了這方便的空白,const與 let 都是塊級作用域。
function f() { { let x; { // 正確 const x = "sneaky"; // 錯誤,常數const x = "foo"; } // 錯誤,已經宣告過的變數 let x = "inner"; } }
1、Array.prototype.includes()
includes() 函數用來判斷一個陣列是否包含一個指定的值,如果包含則返回 true,否則返回 false。
[1, 2, 3].includes(-1) // false [1, 2, 3].includes(1) // true [1, 2, 3].includes(3, 4) // false [1, 2, 3].includes(3, 3) // false [1, 2, NaN].includes(NaN) // true ['foo', 'bar', 'quux'].includes('foo') // true ['foo', 'bar', 'quux'].includes('norf') // false
2、指數操作符
在 ES7 中引入了指數運運算元 **, **具有與 Math.pow(…)等效的計算結果。使用指數運運算元 **,就像 +、- 等操作符一樣。
//之前的版本 Math.pow(5, 2) // ES7 5 ** 2 // 5 ** 2 === 5 * 5
1、async/await
非同步函數返回一個AsyncFunction物件並通過事件迴圈非同步操作。
const resolveAfter3Seconds = function() { console.log('starting 3 second promsise') return new Promise(resolve => { setTimeout(function() { resolve(3) console.log('done in 3 seconds') }, 3000) }) } const resolveAfter1Second = function() { console.log('starting 1 second promise') return new Promise(resolve => { setTimeout(function() { resolve(1) console.log('done, in 1 second') }, 1000) }) } const sequentialStart = async function() { console.log('***SEQUENTIAL START***') const one = await resolveAfter1Second() const three = await resolveAfter3Seconds() console.log(one) console.log(three) } sequentialStart();
2、Object.values()
Object.values()是一個與 Object.keys()類似的新函數,但返回的是 Object 自身屬性的所有值,不包括繼承的值。
const obj = { a: 1, b: 2, c: 3 } //不使用 Object.values() const vals = Object.keys(obj).map((key) => obj[key]) console.log(vals) //使用 Object.values() const values = Object.values(obj1) console.log(values)
從上述程式碼中可以看出 Object.values()
為我們省去了遍歷 key,並根據這些 key 獲取 value 的步驟。
3、Object.entries()
Object.entries()函數返回一個給定物件自身可列舉屬性的鍵值對的陣列。
//不使用 Object.entries() Object.keys(obj).forEach((key) => { console.log('key:' + key + ' value:' + obj[key]) }) //key:b value:2 //使用 Object.entries() for (let [key, value] of Object.entries(obj1)) { console.log(`key: ${key} value:${value}`) } //key:b value:2
4、String padding
在 ES8 中 String 新增了兩個範例函數 String.prototype.padStart和 String.prototype.padEnd,允許將空字串或其他字串新增到原始字串的開頭或結尾。
console.log('0.0'.padStart(4, '10')) console.log('0.0'.padStart(20)) console.log('0.0'.padEnd(4, '0')) console.log('0.0'.padEnd(10, '0'))
5、Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptors()函數用來獲取一個物件的所有自身屬性的描述符,如果沒有任何自身屬性,則返回空物件。
let myObj = { property1: 'foo', property2: 'bar', property3: 42, property4: () => console.log('prop4') } Object.getOwnPropertyDescriptors(myObj) /* { property1: {…}, property2: {…}, property3: {…}, property4: {…} } property1: {value: "foo", writable: true, enumerable: true, configurable: true} property2: {value: "bar", writable: true, enumerable: true, configurable: true} property3: {value: 42, writable: true, enumerable: true, configurable: true} property4: {value: ƒ, writable: true, enumerable: true, configurable: true} __proto__: Object */
1、async iterators
ES9 引入非同步迭代器(asynchronous iterators), await可以和 for…of迴圈一起使用,以序列的方式執行非同步操作。
//如果在 async/await中使用迴圈中去呼叫非同步函數,則不會正常執行 async function demo(arr) { for (let i of arr) { await handleDo(i); } } //ES9 async function demo(arr) { for await (let i of arr) { handleDo(i); } }
2、Promise.finally()
一個 Promise 呼叫鏈要麼成功到達最後一個 .then(),要麼失敗觸發 .catch()。在某些情況下,你想要在無論 Promise 執行成功還是失敗,執行相同的程式碼,例如清除,刪除對話,關閉資料庫連線等。
.finally()允許你指定最終的邏輯。
function doSomething() { doSomething1() .then(doSomething2) .then(doSomething3) .catch((err) => { console.log(err) }) .finally(() => {}) }
3、Rest/Spread屬性
Rest:物件解構賦值的其餘屬性。
Spread:物件解構賦值的傳播屬性。
//Rest let { fname, lname, ...rest } = { fname: "Hemanth", lname: "HM", location: "Earth", type: "Human" }; fname; //"Hemanth" lname; //"HM" rest; // {location: "Earth", type: "Human"} //Spread let info = {fname, lname, ...rest}; info; // { fname: "Hemanth", lname: "HM", location: "Earth", type: "Human" }
1、Array的 flat()方法和 flatMap()方法
flat() 方法會按照一個可指定的深度遞迴遍歷陣列,並將所有元素與遍歷到的子陣列中的元素合併為一個新陣列返回。
flatMap() 方法首先使用對映函數對映每個元素,然後將結果壓縮成一個新陣列。它與 map 和 深度值1的 flat 幾乎相同,但 flatMap通常在合併成一種方法的效率稍微高一些。
let arr = ['a', 'b', ['c', 'd']]; let flattened = arr.flat(); console.log(flattened); // => ["a", "b", "c", "d"] arr = ['a', , , 'b', ['c', 'd']]; flattened = arr.flat(); console.log(flattened); // => ["a", "b", "c", "d"] arr = [10, [20, [30]]]; console.log(arr.flat()); // => [10, 20, [30]] console.log(arr.flat(1)); // => [10, 20, [30]] console.log(arr.flat(2)); // => [10, 20, 30] console.log(arr.flat(Infinity)); // => [10, 20, 30]
2、String的 trimStart()方法和 trimEnd()方法
分別去除字串首尾空白字元
const str = " string "; console.log(str.trimStart()); // => "string " console.log(str.trimEnd()); // => " string"
3、Object.fromEntries()
Object.entries()方法的作用是返回一個給定物件自身可列舉屬性的鍵值對陣列,其排列與使用 for…in 迴圈遍歷該物件時返回的順序一致(區別在於 for-in 迴圈也列舉原型鏈中的屬性)。
而 Object.fromEntries() 則是 Object.entries() 的反轉,Object.fromEntries() 函數傳入一個鍵值對的列表,並返回一個帶有這些鍵值對的新物件。
const myArray = [['one', 1], ['two', 2], ['three', 3]]; const obj = Object.fromEntries(myArray); console.log(obj); // => {one: 1, two: 2, three: 3}
1、Promise.allSettled
Promise.all最大問題就是如果其中某個任務出現異常(reject),所有任務都會掛掉,Promise 直接進入 reject 狀態。
Promise.allSettled在並行任務中,無論一個任務正常或者異常,都會返回對應的的狀態(fulfilled 或者 rejected)與結果(業務 value 或者 拒因 reason),在 then 裡面通過 filter 來過濾出想要的業務邏輯結果,這就能最大限度的保障業務當前狀態的可存取性。
const promise1 = Promise.resolve(3); const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo')); const promises = [promise1, promise2]; Promise.allSettled(promises). then((results) => results.forEach((result) => console.log(result.status))); // expected output: // "fulfilled" // "rejected"
2、String.prototype.matchAll
matchAll() 方法返回一個包含所有匹配正規表示式及分組捕獲結果的迭代器。 在 matchAll出現之前,通過在迴圈中呼叫 regexp.exec來獲取所有匹配項資訊(regexp需使用 /g 標誌)。如果使用 matchAll,就可以不必使用 while 迴圈加 exec 方式(且正規表示式需使用/g標誌)。使用 matchAll會得到一個迭代器的返回值,配合 for…of, array spread, or Array.from() 可以更方便實現功能。
const regexp = /t(e)(st(\d?))/g; const str = 'test1test2'; const array = [...str.matchAll(regexp)]; console.log(array[0]); // expected output: Array ["test1", "e", "st1", "1"] console.log(array[1]); // expected output: Array ["test2", "e", "st2", "2"]
1、Promise.any
Promise.any() 接收一個Promise可迭代物件,只要其中的一個 promise 成功,就返回那個已經成功的 promise 。如果可迭代物件中沒有一個 promise 成功(即所有的 promises 都失敗/拒絕),就返回一個失敗的 promise。
const promise1 = new Promise((resolve, reject) => reject('我是失敗的Promise_1')); const promise2 = new Promise((resolve, reject) => reject('我是失敗的Promise_2')); const promiseList = [promise1, promise2]; Promise.any(promiseList) .then(values=>{ console.log(values); }) .catch(e=>{ console.log(e); });
2、邏輯運運算元和賦值表示式
邏輯運運算元和賦值表示式,新特性結合了邏輯運運算元(&&=,||=,??=)。
a ||= b //等價於 a = a || (a = b) a &&= b //等價於 a = a && (a = b) a ??= b //等價於 a = a ?? (a = b)
3、replaceAll
返回一個全新的字串,所有符合匹配規則的字元都將被替換掉。
const str = 'hello world'; str.replaceAll('l', ''); // "heo word"
4、數位分隔符
數位分隔符,可以在數位之間建立視覺化分隔符,通過_下劃線來分割數位,使數位更具可讀性。
const money = 1_000_000_000; //等價於 const money = 1000000000; 1_000_000_000 === 1000000000; // true
【相關推薦:】
以上就是ecmascript有什麼特性的詳細內容,更多請關注TW511.COM其它相關文章!