摘要:返回布爾值,表示參數字符串是否在源字符串的尾部。我們可以往里面添加刪除查詢數據先聲明一個對象往這個集合對象中添加元素判斷集合中是否存在一個元素返回一個布爾值,表示該值在中存在與否。
一、 ES6 基本語法 1.1 let
作用域就是一個變量的有效的范圍,就是你聲明一個變量以后,這個變量在什么場合可以使用它。以前JavaScript只有全局作用域和函數作用域,現在JavaScript也有了塊級作用域(block scope)
1.1.1 let 語法let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]];1.1.2 參數解釋
var1, var2, …, varN 變量名。可以是任意合法的標識符。1.1.2 let 描述
value1, value2, …, valueN 變量的初始值。可以是任意合法的表達式。
let允許你聲明一個作用域被限制在塊級中的變量、語句或者表達式。與var關鍵字不同的是,它聲明的變量只能是全局或者整個函數塊的。
1.1.3 let 作用域規則let聲明的變量只在其聲明的塊或子塊中可用,這一點,與var相似。二者之間最主要的區別在于var聲明的變量的作用域是整個封閉函數。
看下面的例子:
function varTest() { var x = 1; if (true) { var x = 2; // 同樣的變量! console.log(x); // 2 } console.log(x); // 2 } function letTest() { let x = 1; if (true) { let x = 2; // 不同的變量 console.log(x); // 2 } console.log(x); // 1 }1.2 const 1.2.1 const 語法
const name1 = value1 [, name2 = value2 [, ... [, nameN = valueN]]];1.2.2 參數解釋
nameN1.2.3 const描述
常量名稱,可以是任意合法的標識符。valueN
常量值,可以是任意合法的表達式。
此聲明創建一個常量,其作用域可以是全局或本地聲明的塊。 與var變量不同,全局常量不會變為窗口對象的屬性。需要一個常數的初始化器;也就是說,您必須在聲明的同一語句中指定它的值(這是有道理的,因為以后不能更改)。1.2.4 實例
const聲明創建一個值的只讀引用。但這并不意味著它所持有的值是不可變的,只是變量標識符不能重新分配。例如,在引用內容是對象的情況下,這意味著可以改變對象的內容(例如,其參數)。
1.2.5 小結
如果const后面的變量是普通變量,改變值報錯。如果后面存儲的是數組或者對象,那么改變它的指向也會報錯,但是如果改變數組或者對象的值是不會發生錯誤的1.3 解構賦值
ES6允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱為解構1.3.1 數組的解構賦值
ES5 中的變量賦值,只能直接指定值
var a = 1; var b = 2; var c = 3;
ES6 可以這樣寫
var [a, b, c] = [1, 2, 3]; console.log(a,b,c);// 1 2 3
上面代碼表示,可以從數組中提取值,按照對應位置,對變量賦值。這種寫法屬于“模式匹配”,只要等號兩邊的模式相同,左邊的變量就會被賦予對應的值
1.3.2 允許使用默認值var [a=1] = [] console.log(a);// 1 var [a,b=2] = [3]; console.log(a,b);//3 2 var [a,b=4] = [5,undefined]; console.log(a,b);// 5 41.3.4 使用默認值的注意事項
注意一:
ES6內部使用嚴格相等運算符(===),判斷一個位置是否有值。 所以,如果一個數組成員不嚴格等于undefined,默認值是不會生效的。
var [d=8] = [undefined]; console.log(d);// 8 var [a=9] = [null]; console.log(a);// null
上面代碼中,如果一個數組成員是null,默認值就不會生效,因為null不嚴格等于undefined。
注意二:
如果默認值是一個表達式,那么這個表達式是惰性求值的,即只有在用到的時候,才會求值。
function getNumber(){ console.log("只有用到我的時候我才出現"); } var [a=getNumber()] = ["我先來"]; console.log(a);// 會輸出 我先來
上面代碼中,因為a能取到值,所以函數f根本不會執行。上面的代碼其實等價于下面的代碼。
function getNumber(){ console.log("只有用到我的時候我才出現"); } let a; if(["我先來"][0]===undefined){ a = getNumber(); }else{ a = ["我先來"][0]; } console.log(a);// 會輸出 我先來
注意三:
默認值可以引用解構賦值的其他變量,但該變量必須已經聲明
let [a,b=a]=[1]; console.log(a,b);// a = 1 b = 1 let [x=2,y=x]=[]; console.log(x,y);// x = 2 y = 2 let [c=1,d=c]=[12,3]; console.log(c,d);// c =12 d = 3 let [e=f,f=1]=[]; console.log(e,f);// 報錯 f is not defined
上面最后一個表達式之所以會報錯,是因為e用到默認值f時,f還沒有聲明
1.3.5 對象的解構賦值解構賦值不僅可以用于數組,還可以用于對象.
eg:
let {name,age} = {name:"wxk",age:20}; console.log(name); // wxk
注意:對象的解構與數組有一個重要的不同
- 數組的元素是按次序排列的,變量的取值由它的位置決定 - 對象的屬性沒有次序,變量必須與屬性同名,才能取到正確的值
小編總結:等號左邊的變量的次序,與等號右邊兩個同名屬性的次序不一致,但是對取值完全沒有影響。但是如果變量沒有對應的同名屬性,則會導致取不到值,最后等于undefined1.4 函數 1.4.1 為函數的參數設置默認值
在es6里面我們可以給定義的函數接收的參數設置默認的值,如果不去指定這個函數的參數的值的話,就會使用這些參數的默認的值
function Person(name="Tom",age=12){ console.log(name);//Tom console.log(age);// 12 } Person();
如果在調用函數的時候傳入實參,則會改變默認參數的值。eg:
function Person(name="Tom",age=12){ console.log(name);//Jack console.log(age);// 20 } Person("Jack",20);1.4.2 ... 操作符
...是es6中新添加的一種操作符,可以叫做spread(擴展)或則rest(剩余)
具體用法如下:
rest (剩余操作符)
剩余操作符一般會用在函數的參數里面。比如:
想讓一個函數支持更多的參數,參數的數量不受限制,這個時候就可以 使用剩余操作符。
eg:
剩余操作符后面的變量會變成一個數組,多余的參數會被放入這個數組中
spread(擴展運算符)
...操作符如果用在數組的前面,作用就是將這個數組展開,因此稱為擴展操作符。相當于rest操作符的逆運算
eg:
這里呢把數組arr1 和 數組 arr2 用 ... 操作符進行了擴展,所有他們變成了字符串,不信你們可以嘗試一下,直接輸出 console.log(...arr1)
1.4.3 函數的 name 屬性es6給函數添加了一個name屬性,使用這個屬性我們可以得到函數的名字
eg:
1.4.4 箭頭函數(重點) 箭頭函數的語法
不引入參數
2. 引入單個參數
3. 引入多個參數,則應加上小括號
// ES5 語法 function sum(num1,num2){ return num1 + num2; } // 等同于 // ES6 語法 var sum = (num1,num2)=> num1 + num2; console.log(sum(5,9));//14
4. 若你想使用標準的函數體,或者函數體內可能有更多的語句要執行,則要用大括號將函數體括起來,并明確定義返回值。
// ES6 語法 var sum = (num1, num2) => { return num1 + num2; } //等同于: // ES5 語法 var sum = function(num1, num2) { return num1 + num2; };
5. 箭頭函數若要返回自定義對象的話,就必須用小括號把該對象括起來先
1.4.5 箭頭函數的 this 指向
箭頭函數本身是沒有this和arguments的,在箭頭函數中引用this實際上是調用的是定義時的上一層作用域的this。
這里強調的是上一層作用域,是因為對象是不能形成獨立的作用域的。
看下面的小例子更容易明白:
eg1
eg2:
var ojb = { pro: { getPro: ()=>{ console.log(this); } } } ojb.pro.getPro();//this指向的是window,因為箭頭函數定義時,getPro的上一級是pro,是一個對象,不能形成多帶帶的作用域,故指向window。
總結箭頭函數的this指向:箭頭的this,向上找,找到非箭頭函數,看一下這個非箭頭函數的this是誰,那么箭頭函數的this就是這個非箭頭函數的this。
1.5 字符串 1.5.1 includes(), startsWith(), endsWith()傳統上,JavaScript只有indexOf方法,可以用來確定一個字符串是否包含在另一個字符串中。ES6又提供了三種新方法。
includes():返回布爾值,表示是否找到了參數字符串。
startsWith():返回布爾值,表示參數字符串是否在源字符串的頭部。
endsWith():返回布爾值,表示參數字符串是否在源字符串的尾部。
舉例說明三個方法怎么用:
注意:這三個方法都支持第二個參數,表示開始搜索的位置
1.5.2 模板字符串模板字符串中所有的空格、新行、縮進,都會原樣輸出在生成的字符串中
注意:模板字符串(template string)是增強版的字符串,用反引號(`),標識,嵌入的變量名寫在${}之中
1.6 對象 Object 1.6.1 屬性的簡潔表示法ES6為我們提供了一種簡寫方法,就是在對象里面直接加上這屬性,不需要再指定值
1.6.2 對象新增函數Object.is()ES5比較兩個值是否相等,只有兩個運算符:相等運算符(==)和嚴格相等運算符(===)。它們都有缺點,前者會自動轉換數據類型,后者的NaN不等于自身,以及+0等于-0。JavaScript缺乏一種運算,在所有環境中,只要兩個值是一樣的,它們就應該相等。
ES6提出“Same-value equality”算法,用來解決這個問題。Object.is就是部署這個算法的新方法。它用來比較兩個值是否嚴格相等,與嚴格比較運算符(===)的行為基本一致。
見下面的例子:
1.6.3 對象新增函數Object.assign()
Object.assign方法用于對象的合并,將源對象(source)的所有可枚舉屬性,復制到目標對象(target)
1. 注意:如果目標對象與源對象有同名屬性,或多個源對象有同名屬性,則后 面的屬性會覆蓋前面的屬性
2. 如果只有一個參數,Object.assign會直接返回該參數
var cat = { height:50 } var str = {} Object.assign(str,cat); console.log(str);//{height: 50}
3. 如果該參數不是對象,則會先轉成對象,然后返回
console.log(Object.assign(2));// Number?{2}
4. 由于undefined和null無法轉成對象,所以如果它們作為參數,就會報錯。
1.7 集合對象 1.7.1 Set 對象Set對象是一組值的集合,這些值是不重復的,無序的,與我們在數學中學到的集合是一樣的。我們可以往里面添加、刪除、查詢數據
1. 先聲明一個Set對象
var mySet = new Set();
2. 往這個集合對象中添加元素
mySet.add(1);
mySet.add("some text");
3. 判斷集合中是否存在一個元素1
mySet.has(1); // true 返回一個布爾值,表示該值在Set中存在與否。
4. 刪除集合中的字符串
mySet.delete("foo");//移除Set的中與這個值相等的元素
5. 獲取集合中元素的數量
mySet.size; // 返回Set對象的值的個數。
6. 刪除集合中所有的元素
mySet.clear();//移除Set對象內的所有元素。
1.7.2 Map對象
如果你需要一個鍵值對的數據結構,我們可以聲明一個Map對象,這個對象里面可以包含多個項目,每個項目都有一個名字,還有一個跟它對應的值
1. 創建Map對象的方法是使用new操作符去聲明這個對象
var myMap = new Map();
2. 向Map對象里面添加鍵值對,其中鍵和值可以是任意值(對象或者原 始值)
var obj = {};
var fun = function(){}; var str = “HelloWorld”; myMap.set(obj, “我是對象”); myMap.set(fun, “我是函數”); myMap.set(str, “我是字符串”);
3. 查看集合中元素的數量
myMap.size
4. 獲取相應的鍵值
myMap.get(obj);
5. 刪除一個鍵值對,然后再判斷該鍵值對是否存在
myMap.delete(fun);
myMap.has(fun);
6. 刪除Map集合中所有的鍵值對
myMap.clear();
eg:
其余的方法就不演示了,和上面的Set方法一樣
1.7.3 Class (重點)ES6提供了更接近傳統語言的寫法,引入了Class(類)這個概念,作為對象的模板。通過class關鍵字,可以定義類。基本上,ES6的class可以看作只是一個語法糖,它的絕大部分功能,ES5都可以做到,新的class寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的語法而已。上面的代碼就可以這樣改
class person { constructor(name,age){ this.name = name; this.age = age; } run(){ console.log("每天堅持鍛煉"); } } var student = new person("Jack",15); student.run();
小編分析:上面代碼定義了一個“類”,可以看到里面有一個constructor方法, 這就是構造方法,而this關鍵字則代表實例對象。也就是說,ES5的構造函數person,對應ES6的person類的構造方法。person類除了構造方法,還定義了一個run方法。注意,定義“類”方法的時候,前面不需要加上function這個關鍵字,直接把函數定義放進去了就可以了。另外,方法之間不需要逗號分隔,加了會報錯。構造函數的prototype屬性,在ES6的“類”上面繼續存在。事實上,類的所有方法都定義在類的prototype屬性上面
1.7.4 class繼承 (重點)extends關鍵字用于實現類之間的繼承。子類繼承父類,就繼承了父類的所有屬性和方法,使用super可以調用父類的方法
1.8 Promise對象 1.8.1 什么是Promise對象一個 Promise 對象可以理解為一次將要執行的操作(常常被用于異步操作),使用了 Promise 對象之后可以用一種鏈式調用的方式來組織代碼,讓代碼更加直觀。而且由于 Promise.all 這樣的方法存在,可以讓同時執行多個操作變得簡單
下面簡單介紹Promise 對象,如下代碼:
上面的代碼實現的功能非常簡單,helloWord 函數接受一個參數,如果為 true 就打印 "Hello World!",如果為 false 就打印錯誤的信息。helloWord 函數返回的是一個 Promise 對象。1.8.2 Promise的三種狀態在 Promise 對象當中有兩個重要方法————resolve 和 reject。
resolve 方法可以使 Promise 對象的狀態改變成成功,同時傳遞一個參數用于后續成功后的操作,在這個例子當中就是 Hello World!字符串
reject 方法則是將 Promise 對象的狀態改變為失敗,同時將錯誤的信息傳遞到后續錯誤處理的操作
resolved 可以理解為成功的狀態
rejected 可以理解為失敗的狀
pending promise對象實例創建時候的初始狀態
helloWorld 的例子中的 then 方法就是根據 Promise 對象的狀態來確定執行的操作,resolve 時執行第一個函數(onFulfilled),reject 時執行第二個函數(onRejected)
如何查看Promise對象的方法,在控制臺輸出 new Promise(function(){})
見下圖:
### 1.8.3 使用Promise處理多任務
看下面的例子:
function HelloWorld(ready){ return new Promise(function(resolve,reject){ if(ready){ resolve("HelloWorld"); }else{ reject("GoodBay"); } }); } HelloWorld(true).then(function(message){ console.log(message); },function(error){ console.log(error); }).then(function(){ console.log("你好,世界!"); }).then(function(){ console.log("講真的"); });
解析:可以看到后面的方法用了鏈式的方式進行編程,這是因為,then返回的還是一個 Promise 對象,因此返回的對象依然具有 then 方法,并且返回的對象狀態是 resolved, 所以后面的 then方法全部是執行then 方法中的第一個函數參數1.8.4 catch方法
catch 方法是 then(onFulfilled, onRejected) 方法當中 onRejected 函數的一個簡單的寫法,也就是說可以寫成then(fn).catch(fn),相當于 then(fn).then(null, fn)。使用 catch 的寫法比一般的寫法更加清晰明確1.8.5 all和race方法
console.time(); var p1 = new Promise(function(resolve) { setTimeout(function() { resolve("Hello"); }, 3000); }); var p2 = new Promise(function(resolve) { setTimeout(function() { resolve("world"); }, 3000); }) Promise.all([p1, p2]).then(function(result) { console.log(result); console.timeEnd(); });
上面的例子模擬了傳輸兩個數據需要不同的時長,雖然 p2 的速度比 p1 要快,但是 Promise.all 方法會按照數組里面的順序將結果返回
日常開發中經常會遇到這樣的需求,在不同的接口請求數據然后拼合成自己所需的數據,通常這些接口之間沒有關聯(例如不需要前一個接口的數據作為后一個接口的參數),這個時候 Promise.all 方法就可以派上用場了
還有一個和 Promise.all 相類似的方法 Promise.race,它同樣接收一個數組,不同的是只要該數組中的 Promise 對象的狀態發生變化(無論是 resolve 還是 reject)該方法都會返回1.9 fetch網絡請求
與ajax 請求的對比見下面的代碼:
如果有需要可以按照上面的方式進行編寫
二、ES6之Module系統 2.1 為什么要進行模塊化?可維護性的需要
可測性的需要
性能的需要
架構的需求
代碼復用
多人協作的需要
2.2 導入導出小編這里只說步驟:
第一步:在你需要導出的 js 文件中某個方法或對象時,前面加上 export 關鍵字
第二步: 在另一個js文件中導入你要導出的js文件,import 對象/方法 from ×××.js
第三步: 在html中引入入口js 文件,就是第二步中的另一個js文件。