一文了解ES5和ES6的區(qū)別
我們都知道JavaScript是由三部分組成:
1. ECMAScript(核心):規(guī)定了語言的組成部分=>語法、類型、語句、關鍵字、保留字、操作符、對象
2. BOM(瀏覽器對象模型): 支持訪問和操作瀏覽器窗口,可以控制瀏覽器顯示頁面以外的部分。
3. DOM(文檔對象模型): 把整個頁面映射為一個多層節(jié)點結果,可借助DOM提供的API,可刪除、添加和修改任何節(jié)點
什么是ES5?
ES5全稱ECMAScript5,即 ES5,是ECMAScripts的第五次修訂(第四版因為過于復雜廢棄了),又稱ECMAScript2009,于 2009 年完成標準化。
什么是ES6?
ES6, 全稱 ECMAScript 6.0 ,即 ES6,是ECMAScripts的第六次修訂,又稱 ES2015,于2015年06 月發(fā)版,是 JavaScript 的下一個版本標準。
ES6 主要是為了解決 ES5 的先天不足,目前瀏覽器的 JavaScript 是 ES5 版本,大多數(shù)高版本的瀏覽器也支持 ES6,不過只實現(xiàn)了 ES6 的部分特性和功能。ES6 是繼 ES5 之后的一次改進,相對于 ES5 更加簡潔,提高了開發(fā)效率
首先,說說ES5的特性:
1. strict模式:嚴格模式,限制一些用法。
2. Array增加方法:有every、some、forEach、filter、indexOf、lastIndexOf、isArray、map、reduce、reduceRight方法。
3. Object方法: Object.getPrototypeOf、Object.create等方法。
- Object.getPrototypeOf
- Object.create
- Object.getOwnPropertyNames
- Object.defineProperty
- Object.getOwnPropertyDescriptor
- Object.defineProperties
- Object.keys
- Object.preventExtensions / Object.isExtensible
- Object.seal / Object.isSealed
- Object.freeze / Object.isFrozen
其次,談談ES6的特性:
1. 塊級作用域 => 關鍵字let,常量const
在 ES6 中通常用 let 和 const 來聲明,let 表示變量、const 表示常量
?? 特點
let 和 const 都是塊級作用域。以{}代碼塊作為作用域范圍 只能在代碼塊里面使用,不存在變量提升,只能先聲明再使用,否則會報錯。在代碼塊內(nèi),在聲明變量之前,該變量 都是不可用的。這在語法上,稱為“暫時性死區(qū)”(temporal dead zone,簡稱 TDZ),在同一個代碼塊內(nèi),不允許重復聲明。
const 聲明的是一個只讀常量,在聲明時就需要賦值。(如果 const 的是一個對象,
對象所包含的值是可以被修改的。抽象一點兒說,就是對象所指向的地址不能改變,而
變量成員 是可以修改的。)
2. 對象的擴展
?? 屬性和方法的簡寫
對象字面量屬性的簡寫
ES6 允許在對象之中,直接寫變量。這時,屬性名為變量名, 屬性值為變量的值。
var foo = 'bar'; var baz = {foo}; // 等同于 var baz = {foo: foo};對象字面量方法的簡寫。省略冒號與 function 關鍵字
var o = { method() { return "Hello!"; } }; // 等同于 var o = { method: function () { return "Hello!"; } };?? Object.keys()方法
獲取對象的所有屬性名或方法名(不包括原形的內(nèi)容),返回一個數(shù)組。
var obj={name: "john", age: "21", getName: function () { alert(this.name)}}; console.log(Object.keys(obj)); // ["name", "age", "getName"] console.log(Object.keys(obj).length); //3 console.log(Object.keys(["aa", "bb", "cc"])); //["0", "1", "2"] console.log(Object.keys("abcdef")); //["0", "1", "2", "3", "4", "5"]?? Object.assign ()
assign 方法將多個原對象的屬性和方法都合并到了目標對象上面。可以接收多個參
數(shù),第一個參數(shù)是目標對象,后面的都是源對象
var target = {}; //目標對象 var source1 = {name : 'ming', age: '19'}; //源對象 1 var source2 = {sex : '女'}; //源對象 2 var source3 = {sex : '男'}; //源對象 3,和 source2 中的對象有同名屬性 sex Object.assign(target,source1,source2,source3); console.log(target); //{name : 'ming', age: '19', sex: '男'}
3. 解構賦值
?? 數(shù)組的解構賦值
解構賦值是對賦值運算符的擴展。是一種針對數(shù)組或者對象進行模式匹配,然后對其中的變量進行賦值。在代碼書寫上簡潔且易讀,語義更加清晰明了;也方便了復雜對象中數(shù)據(jù)字段獲取。數(shù)組中的值會自動被解析到對應接收該值的變量中,數(shù)組的解構賦值要一一對應如果
有對應不上的就是 undefined
let [a, b, c] = [1, 2, 3]; // a = 1 // b = 2 // c = 3?? 對象的解構賦值
對象的解構賦值和數(shù)組的解構賦值其實類似,但是數(shù)組的數(shù)組成員是有序的,而對象的屬性則是無序的,所以對象的解構賦值簡單理解是等號的左邊和右邊的結構相同。
let { foo, bar } = { foo: 'aaa', bar: 'bbb' }; // foo = 'aaa' // bar = 'bbb' let { baz : foo } = { baz : 'ddd' }; // foo = 'ddd'
4. 展開運算符(Spread operator)
展開運算符(spread operator)允許一個表達式在某處展開。展開運算符在多個參數(shù)(用于函數(shù)調(diào)用)或多個元素(用于數(shù)組字面量)或者多個變量(用于解構賦值)的地方可以使用。
let obj1 = { value1: 1, value2: 2 }; let obj2 = {...obj1 }; console.log(obj2); // {value1: 1, value2: 2}上面的用法實際相當于
obj2 = {value1: 1, value2: 2}展開運算符的寫法與
obj2 = obj1
直接賦值的寫法的區(qū)別在于如果直接賦值的話,對于引用類型
來說,相當于只是賦值了obj1
的內(nèi)存空間地址,當obj2
發(fā)生改變的時候,obj1
也會隨著發(fā)生改變。而是用展開運算符
寫法的話,由于obj1
對象中的屬性類型都是基本類型
,相當于重新創(chuàng)建了一個對象,此時obj2
發(fā)生改變的時候,并不會影響obj1
這個對象。但是僅限于其屬性都為基本類型的情況(或者說只進行了一層的深拷貝)。如果該對象中的屬性還有引用類型的話,修改屬性中引用類型的值,則兩個對象的屬性值都會被修改。展開運算符的應用let obj1 = { attri1: [3, 6, 0], attri2: 4, attri4: 5 }; let obj2 = {...obj1 }; obj2.attri2 = 888; obj2.attri1[0] = 7; console.log('obj1:', obj1); console.log('obj2:', obj2);1.在函數(shù)中使用展開運算符
function test(a, b, c){}; let arr = [1, 2, 3]; test(...arr);2.數(shù)組字面量中使用展開運算符
let arr1 = [1, 2]; let arr2 = [...arr1, 3, 4]; // [1, 2, 3, 4] // 使用push方法 let arr1 = [1, 2]; let arr2 = [3. 4]; arr1.push(...arr2); // [1, 2, 3, 4]3.用于解構賦值,解構賦值中展開運算符只能用在最后,否則會報錯。
// 解構賦值中展開運算符只能用在最后。 let [a, b, ...c] = [1, ,2, 3, 4] console.log(a, b, c) // 1, 2, [3, 4]4.類數(shù)組變成數(shù)組
let oLis = document.getElementsByTagName("li"); let liArr = [...oLis];5.對象中使用展開運算符
ES7中的對象展開運算符符可以讓我們更快捷地操作對象:
let {x,y,...z}={x:1,y:2,a:3,b:4}; x; // 1 y; // 2 z; // {a:3,b:4}將一個對象插入另外一個對象當中:
let z={a:3,b:4}; let n={x:1,y:2,...z}; console.log(n); //{x:1,y:2,a:3,b:4}合并兩個對象:
let a={x:1,y:2}; let b={z:3}; let ab={...a,...b}; console.log(ab); // {x:1,y:2,z:3}
5. 函數(shù)的擴展
?? 函數(shù)的默認參數(shù)
ES6 為參數(shù)提供了默認值。在定義函數(shù)時便初始化了這個參數(shù),以便在參數(shù)沒有被傳
遞進去時使用。
?? 箭頭函數(shù)
在 ES6 中,提供了一種簡潔的函數(shù)寫法,我們稱作“箭頭函數(shù)”。
寫法:函數(shù)名=(形參)=>{……} 當函數(shù)體中只有一個表達式時,{}和 return 可以省 略
當函數(shù)體中形參只有一個時,()可以省略。
特點:箭頭函數(shù)中的 this 始終指向箭頭函數(shù)定義時的離 this 最近的一個函數(shù),如果沒有最
近的函數(shù)就指向 window。
6. 模板字符串
用一對反引號(`)標識,它可以當作普通字符串使用,也可以用來定義多行字符串,也可以
在字符串中嵌入變量,js 表達式或函數(shù),變量、js 表達式或函數(shù)需要寫在${ }中。
var name = "Bob", time = "today"; `Hello ${name}, how are you ${time}?` // return "Hello Bob, how are you today?"
7. for...of循環(huán)
var arr=["小林","小吳","小佳"]; for(var v of arr){ console.log(v); } //小林 //小吳 //小佳
8. Class類,有constructor、extends、super,本質(zhì)上是語法糖,(對語言的功能并沒有影響,但是更方便程序員使用)。
class Artist { constructor(name) { this.name = name; } perform() { return this.name + " performs "; } } class Singer extends Artist { constructor(name, song) { super.constructor(name); this.song = song; } perform() { return super.perform() + "[" + this.song + "]"; } } let james = new Singer("Etta James", "At last"); james instanceof Artist; // true james instanceof Singer; // true james.perform(); // "Etta James performs [At last]"
class 類的繼承 ES6 中不再像 ES5 一樣使用原型鏈實現(xiàn)繼承,而是引入 Class 這個概念。
?? ES6 所寫的類相比于 ES5 的優(yōu)點:
區(qū)別于函數(shù),更加專業(yè)化(類似于 JAVA 中的類);
寫法更加簡便,更加容易實現(xiàn)類的繼承;
9. Map + Set + WeakMap + WeakSet
四種集合類型,WeakMap、WeakSet作為屬性鍵的對象如果沒有別的變量在引用它們,則會被回收釋放掉。
// Sets var s = new Set(); s.add("hello").add("goodbye").add("hello"); s.size === 2; s.has("hello") === true; // Maps var m = new Map(); m.set("hello", 42); m.set(s, 34); m.get(s) == 34; //WeakMap var wm = new WeakMap(); wm.set(s, { extra: 42 }); wm.size === undefined // Weak Sets var ws = new WeakSet(); ws.add({ data: 42 });//Because the added object has no other references, it will not be held in the set
10. Math + Number + String + Array + Object APIs
一些新的API
Number.EPSILON Number.isInteger(Infinity) // false Number.isNaN("NaN") // false Math.acosh(3) // 1.762747174039086 Math.hypot(3, 4) // 5 Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2 "abcde".includes("cd") // true "abc".repeat(3) // "abcabcabc" Array.from(document.querySelectorAll('*')) // Returns a real Array Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior [0, 0, 0].fill(7, 1) // [0,7,7] [1, 2, 3].find(x => x == 3) // 3 [1, 2, 3].findIndex(x => x == 2) // 1 [1, 2, 3, 4, 5].copyWithin(3, 0) // [1, 2, 3, 1, 2] ["a", "b", "c"].entries() // iterator [0, "a"], [1,"b"], [2,"c"] ["a", "b", "c"].keys() // iterator 0, 1, 2 ["a", "b", "c"].values() // iterator "a", "b", "c" Object.assign(Point, { origin: new Point(0,0) })
11. proxies:使用代理(Proxy)監(jiān)聽對象的操作,然后可以做一些相應事情。
var target = {}; var handler = { get: function (receiver, name) { return `Hello, ${name}!`; } }; var p = new Proxy(target, handler); p.world === 'Hello, world!';
可監(jiān)聽的操作: get、set、has、deleteProperty、apply、construct、getOwnPropertyDescriptor、defineProperty、getPrototypeOf、setPrototypeOf、enumerate、ownKeys、preventExtensions、isExtensible。
12. Symbol: 唯一命名
Symbol是一種基本類型。Symbol 通過調(diào)用symbol函數(shù)產(chǎn)生,它接收一個可選的名字參數(shù),該函數(shù)返回的symbol是唯一的。
var key = Symbol("key"); var key2 = Symbol("key"); key == key2 //false
13. Promises:處理異步操作的對象,使用了Promise對象之后可以用一種鏈式調(diào)用的方式來組織代碼,讓代碼更加直觀(類似jQuery的deferred 對象)。
function fakeAjax(url) { return new Promise(function (resolve, reject) { // setTimeouts are for effect, typically we would handle XHR if (!url) { return setTimeout(reject, 1000); } return setTimeout(resolve, 1000); }); } // no url, promise rejected fakeAjax().then(function () { console.log('success'); },function () { console.log('fail'); });
Promise 對象Promise 是異步編程的一種解決方案,將異步操作以同步操作的流程表達出來,避免了層層嵌套的回調(diào)函數(shù),要是為了解決異步處理回調(diào)地獄(也就是循環(huán)嵌套的問題)而產(chǎn)生的。
Promise 構造函數(shù)包含一個參數(shù)和一個帶有 resolve(解析)和 reject(拒絕)兩個參數(shù)的
回調(diào)。在回調(diào)中執(zhí)行一些操作(例如異步),如果一切都正常,則調(diào)用 resolve,否則調(diào)用
reject。
對于已經(jīng)實例化過的 Promise 對象可以調(diào)用 Promise.then() 方法,傳遞 resolve 和
reject方法作為回調(diào)。
then()方法接收兩個參數(shù):onResolve 和 onReject,分別代表當前Promise 對象在成功或失敗時Promise 的 3 種狀態(tài):Fulfilled 為成功的狀態(tài),Rejected 為失敗的狀態(tài),Pending 既不是 Fulfilld 也不是Rejected 的狀態(tài),可以理解為 Promise 對象實例創(chuàng)建時候的初始狀態(tài)
14. import 和 export
ES6 標準中,JavaScript 原生支持模塊(module)。這種將 JS 代碼分割成不同功能的小塊進
行模塊化,將不同功能的代碼分別寫在不同文件中,各模塊只需導出公共接口部分,然后通
過模塊的導入的方式可以在其他地方使用。
export 用于對外輸出本模塊(一個文件可以理解為一個模塊)變量的接口。
import 用于在一個模塊中加載另一個含有 export 接口的模塊。
import 和 export 命令只能在模塊的頂部,不能在代碼塊之中。
15、Set 數(shù)據(jù)結構
Set是 ES6 提供的一種新的數(shù)據(jù)結構,類似于數(shù)組。所有的數(shù)據(jù)都是唯一的,沒有重復的值。它本身是一個構造函數(shù)。由于成員都是唯一的,不重復的特點,因此可以通過
Set
輕松實現(xiàn)對數(shù)組的 去重、交、并、補等操作。?? Set 屬性和方法
Size() 數(shù)據(jù)的長度
Add() 添加某個值,返回 Set 結構本身。
Delete() 刪除某個值,返回一個布爾值,表示刪除是否成功。
Has() 查找某條數(shù)據(jù),返回一個布爾值。
Clear()清除所有成員,沒有返回值。
interface Set { add(value): this; clear(): void; delete(value): boolean; forEach(callbackfn: (value, value2, set: Set) => void, thisArg?: any): void; has(value): boolean; readonly size: number; }?? Set主要應用場景:數(shù)組去重、交集、并集、補集。
根據(jù)
Set
的特點,有很多場景可以通過Set
快速實現(xiàn)。JavaScript Set 實用場景(數(shù)組: 去重、交、并、補)let arr1 = [1, 2, 3, 4, 5, 6, 7, 4, 3, 2, 1]; // 去重 let newArr = [...new Set(arr1)]; console.log(arr1); // [LOG]: [ 1, 2, 3, 4, 5, 6, 7, 4, 3, 2, 1 ] console.log(newArr); // [LOG]: [ 1, 2, 3, 4, 5, 6, 7 ]let arr1 = [1, 2, 3, 4, 5]; let arr2 = [3, 4, 5, 6, 7]; let arr1_set = new Set(arr1); let arr2_set = new Set(arr2); // 交集 let intersectionArr = [...arr1_set].filter(val => arr2_set.has(val)); console.log(intersectionArr ); // [LOG]: [ 3, 4, 5] // 并集 let unionArr = [...new Set([...arr1, ...arr2])]; console.log(unionArr ); // [LOG]: [ 1, 2, 3, 4, 5, 6, 7 ] // 補集 let complementaryArr = [...arr1_set].filter(val => !arr2_set.has(val)); console.log(complementaryArr ); // [LOG]: [ 1, 2 ]
15. Modules
ES6的內(nèi)置模塊功能借鑒了CommonJS和AMD各自的優(yōu)點:
(1) 具有CommonJS的精簡語法、唯一導出出口(single exports)和循環(huán)依賴(cyclic dependencies)的特點。
(2) 類似AMD,支持異步加載和可配置的模塊加載。
// lib/math.js export function sum(x, y) { return x + y; } export var pi = 3.141593; // app.js import * as math from "lib/math"; alert("2π = " + math.sum(math.pi, math.pi)); // otherApp.js import {sum, pi} from "lib/math"; alert("2π = " + sum(pi, pi)); Module Loaders: // Dynamic loading – ‘System' is default loader System.import('lib/math').then(function(m) { alert("2π = " + m.sum(m.pi, m.pi)); }); // Directly manipulate module cache System.get('jquery'); System.set('jquery', Module({$: $})); // WARNING: not yet finalized
最后,我們來看看ES5和ES6的區(qū)別:
1. 系統(tǒng)庫的引入
ES5:需要先使用require導入React包,成為對象,再去進行真正引用;
ES6:可以使用import方法來直接實現(xiàn)系統(tǒng)庫引用,不需要額外制作一個類庫對象
2. 導出及引用單個類
ES5:要導出一個類給別的模塊用,一般通過module.exports來實現(xiàn)。引用時,則依然通過require方法來獲??;
ES6:可以使用用export default來實現(xiàn)相同的功能,使用import方法來實現(xiàn)導入
3. 定義組件
ES5:組件類的定義可以通過React.createClass實現(xiàn)
ES6:讓組件類去繼承React.Component類就可以了
4. 組件內(nèi)部定義方法
ES5:采用的是 ###:function()的形式,方法大括號末尾需要添加逗號;
ES6:省略了【: function】這一段,并且結尾不需要加逗號來實現(xiàn)分隔。
5. 定義組件的屬性類型和默認屬性
ES5:屬性類型和默認屬性分別通過propTypes成員和getDefaultProps方法來實現(xiàn)(這兩個方法應該是固定名稱的);
ES6:統(tǒng)一使用static成員來實現(xiàn)。
6. 初始化STATE
ES5:初始化state的方法是固定的getInitialState;
ES6:第一種,直接構造state函數(shù);第二種,相當于OC中的方法重寫,重寫constructor方法
總結
到此這篇關于ES5和ES6的區(qū)別的文章就介紹到這了,更多相關ES5和ES6區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
JavaScript函數(shù)式編程(Functional Programming)箭頭函數(shù)(Arrow functions)
這篇文章主要介紹了JavaScript函數(shù)式編程(Functional Programming)箭頭函數(shù)(Arrow functions)用法,結合實例形式分析了javascript函數(shù)式編程中箭頭函數(shù)相關概念、原理、用法及操作注意事項,需要的朋友可以參考下2019-05-05javascript函數(shù)的四種調(diào)用模式
本文詳細介紹了javascript函數(shù)的四種調(diào)用模式。具有一定的參考價值,下面跟著小編一起來看下吧2017-01-01檢查輸入的是否是數(shù)字使用keyCode配合onkeypress事件
檢查輸入的是否是數(shù)字在本文使用keyCode配合onkeypress事件來實現(xiàn),具體示例如下2014-01-01JavaScript實現(xiàn)瀏覽器內(nèi)多個標簽頁之間通信
這篇文章主要為大家詳細介紹了JavaScript如何實現(xiàn)瀏覽器內(nèi)多個標簽頁之間通信,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2024-04-04