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