更多詳細可以查看1.1 ES6 教程 | 菜鳥教程
這里我將大概記錄ES與JS大概不一樣的部分,方便聯合記憶。
歷史與關系
- ECMAScript:是一種由 Ecma 國際組織制定的腳本語言規范,它是 JavaScript 的標準化版本。ECMAScript 為 JavaScript 提供了語法、類型、語句、關鍵字等基礎規范,隨著時間推移不斷發展和更新版本。
- JavaScript:是一種廣泛應用于網頁開發等領域的編程語言,它遵循 ECMAScript 規范,并由各大瀏覽器廠商進行實現和擴展。除了 ECMAScript 規定的核心特性外,JavaScript 還包括宿主環境(如瀏覽器)提供的 API,如 DOM、BOM 等。
變量聲明
- JS(ES5 及以前):使用
var
聲明變量,存在變量提升現象,即變量可以在聲明之前使用,其作用域為函數級作用域。例如:
function test() {console.log(x); // 輸出undefinedvar x = 10;
}
test();
- ES6:引入了
let
和const
。let
聲明的變量具有塊級作用域,不存在變量提升,在聲明之前訪問會報錯,稱為 “暫時性死區”。const
用于聲明常量,一旦聲明,不可重新賦值,且也具有塊級作用域,當然,僅在一個代碼塊內的聲明let和const變量,僅在代碼塊內有效。例如:
{let y = 20;const z = 30;
}
console.log(y); // 報錯,y is not defined
console.log(z); // 報錯,z is not defined
?傳統 JavaScript 使用var
聲明變量,存在函數級作用域和變量提升現象。例如,var
聲明的變量可以在聲明之前被訪問,值為undefined
,而let
和const
聲明的變量不存在變量提升,在聲明之前訪問會報錯。
函數
- JS(ES5 及以前):函數聲明有函數聲明語句和函數表達式兩種方式,
this
指向在運行時根據函數的調用方式確定,在全局函數中,this
指向全局對象(瀏覽器中是window
),在對象方法中,this
指向調用該方法的對象。例如:
function add(a, b) {return a + b;
}
const subtract = function (a, b) {return a - b;
};
- ES6:引入了箭頭函數,語法為
(param1, param2, ...) => { function body },
箭頭函數沒有自己的this
,它的this
繼承自外層作用域,更適合用于回調函數等場景,避免了this
指向不明確的問題。例如:
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((num) => num * 2);
與傳統的function
關鍵字定義的函數相比,箭頭函數沒有自己的this
綁定,它的this
指向定義時所在的外層作用域,避免了一些常見的this
指向問題。?
數組
- JS(ES5 及以前):有
push
、pop
、shift
、unshift
等方法用于操作數組。例如:
const arr = [1, 2, 3];
arr.push(4);
arr.shift();
- ES6:增加了
find
、findIndex
、includes
等方法。find
用于找到數組中滿足條件的第一個元素,findIndex
用于找到滿足條件的第一個元素的索引,includes
用于判斷數組是否包含某個元素。例如:
const numbers = [1, 2, 3, 4, 5];
const found = numbers.find((num) => num > 3);
const index = numbers.findIndex((num) => num === 4);
const hasFive = numbers.includes(5);
對象
- JS(ES5 及以前):通過對象字面量或構造函數創建對象,使用點語法或方括號語法訪問屬性。例如:
const person = {name: 'John',age: 30
};
console.log(person.name);
console.log(person['age']);
- ES6:允許對象屬性的簡潔表示法,即屬性名和變量名相同時可以簡寫。還增加了
Object.assign
方法用于對象的合并,Object.keys
、Object.values
、Object.entries
方法用于獲取對象的鍵、值和鍵值對數組。例如:
const name = 'Alice';
const age = 25;
const person = { name, age }; // 簡潔表示法
const obj1 = { a: 1 };
const obj2 = { b: 2 };
const merged = Object.assign({}, obj1, obj2);
const keys = Object.keys(person);
const values = Object.values(person);
const entries = Object.entries(person);
模塊
- JS(ES5 及以前):沒有原生的模塊系統,通常使用第三方庫如
RequireJS
等來實現模塊加載。 - ES6:引入了原生的模塊系統,使用
import
和export
關鍵字來導入和導出模塊。例如:
// 定義模塊 math.js
export function add(a, b) {return a + b;
}
export function subtract(a, b) {return a - b;
}
import { add, subtract } from './math.js';
console.log(add(5, 3));
console.log(subtract(5, 3));
字符串
- JS(ES5 及以前):有
charAt
、indexOf
、substring
等方法操作字符串。
const str = 'Hello, World!';
console.log(str.charAt(0));
console.log(str.indexOf('World'));
console.log(str.substring(7, 12));
- ES6:增加了
includes
、startsWith
、endsWith
等方法,用于更方便地判斷字符串是否包含某個子串、是否以某個子串開頭或結尾。
const str = 'Hello, World!';
console.log(str.includes('World'));
console.log(str.startsWith('Hello'));
console.log(str.endsWith('!'));
數據類型與結構
- Symbol 類型
- 一種新的數據類型,
Symbol
值是唯一的、不可變的,常用于創建對象的唯一屬性鍵,避免屬性名沖突。 - 在 ES6 之前,JavaScript 的基本數據類型只有
number
、string
、boolean
、null
、undefined
,Symbol
的引入為對象屬性的管理提供了更強大的方式。
let sy = Symbol("KK");
console.log(sy); // Symbol(KK)
typeof(sy); // "symbol"// 相同參數 Symbol() 返回的值不相等
let sy1 = Symbol("kk");
sy === sy1; // false
- 解構賦值
- 可以方便地從數組或對象中提取值,并賦值給多個變量。例如,
const [a, b, c] = [1, 2, 3]
可以將數組中的值分別賦給a
、b
、c
;const { name, age } = { name: 'John', age: 30 }
可以從對象中提取name
和age
屬性并賦值給同名變量。 - 傳統的賦值方式需要逐個進行賦值操作,解構賦值更加簡潔和直觀,提高了代碼的可讀性和便利性,尤其在處理函數返回多個值或對象屬性較多的情況時優勢明顯。
面向對象編程
- 類的語法
- 使用
class
關鍵字來定義類,包括構造函數、實例方法和靜態方法等。
- 使用
class Person {constructor(name, age) {this.name = name;this.age = age;}sayHello() {console.log(`Hello, my name is ${this.name}`);}static createPerson(name, age) {return new Person(name, age);}
}
在 ES6 之前,JavaScript 通過構造函數和原型鏈來模擬類和繼承,代碼結構相對復雜且不直觀。class
語法使 JavaScript 的面向對象編程更加清晰和易于理解,與其他面向對象編程語言的語法更加相似。
- 繼承:使用
extends
關鍵字實現類的繼承,super
關鍵字用于調用父類的構造函數和方法。
class Student extends Person {constructor(name, age, grade) {super(name, age);this.grade = grade;}sayHello() {super.sayHello();console.log(`I'm in grade ${this.grade}`);}
}
ES6 之前的繼承實現需要手動操作原型鏈,容易出現一些問題,如原型鏈混亂、子類實例無法正確訪問父類屬性等。extends
和super
的使用使繼承的實現更加規范和可靠。
異步編程
- Promise是一種用于處理異步操作的對象,它代表了一個異步操作的最終完成(或失敗)及其結果值。可以使用
then
方法來處理成功的結果,catch
方法來處理失敗的情況。 - 在 Promise 出現之前,JavaScript 的異步操作通常使用回調函數來處理,但回調函數容易導致回調地獄,即多層嵌套的回調函數使代碼難以閱讀和維護。Promise 通過鏈式調用的方式使異步操作的代碼更加清晰和易于管理。
- async/await
- ES7 引入:基于 Promise 之上的異步函數語法,
async
函數返回一個 Promise 對象,await
只能在async
函數內部使用,用于暫停函數執行,等待 Promise 被解決(resolved)或被拒絕(rejected)。 - 與 Promise 的
then
鏈式調用相比,async/await
使異步代碼看起來更像同步代碼,大大提高了異步代碼的可讀性和可維護性,減少了異步操作帶來的復雜性。
- ES7 引入:基于 Promise 之上的異步函數語法,
模塊系統
- ES6 模塊
- ES6 引入:使用
import
和export
關鍵字來實現模塊的導入和導出。可以將不同的功能封裝在不同的模塊中,通過export
暴露需要對外提供的變量、函數、類等,通過import
在其他模塊中引入這些內容。 - 在 ES6 之前,JavaScript 沒有官方的模塊系統,開發者通常使用各種第三方庫(如 CommonJS、AMD 等)來實現模塊功能。ES6 模塊系統提供了標準化的模塊定義和加載方式,使代碼的組織和管理更加規范和高效。
- ES6 引入:使用
(未完待續)
這些 ES 的特性極大地豐富和增強了 JavaScript 的功能和表現力,使開發者能夠更方便、高效地編寫復雜的前端應用程序。在學習和使用 JavaScript 時,掌握這些 ES 的重要特性是非常關鍵的。