目標:學習 ES6的新語法;爲未來的工做打下基礎;javascript
ES6 介紹html
let const:定義變量的新途徑;前端
解構賦值:快速給變量賦值;java
內置對象的擴展:加強功能;node
ES 6 降級處理:對不支持es6版本的環境如何處理?git
提供了更加方便的新語法彌補 JS 語言自己的缺陷,新增了便捷的語法程序員
給內置對象增長了更多的方法es6
ES6 讓 JS 能夠開發複雜的大型項目,成爲企業級開發語言github
新的前端項目中大量使用 ES6 的新語法面試
ECMAScript 6,簡稱ES6 。它是一種語言標準,6表示版本號。 它是Ecma國際(European Computer Manufacturers Association)於2015年6月正式發佈的 JavaScript 語言的下一代標準,正式名爲ECMAScript 2015(簡寫ES2015)。它的目標是使得JavaScript語言能夠用來編寫複雜的大型應用程序,成爲企業級開發語言。相比較ES5(2011年發佈的),它改進是很是大的,因此在一些場景下ES6也泛指ES2015及以後的新增特性,雖然以後的版本應當稱爲ES七、ES8等,但統稱es6。
ECMA的第39號技術專家委員會(Technical Committee 39,簡稱TC39)負責制訂ECMAScript標準組織每一年都會發布ECMAScript的版本
ES2015:稱爲es6。
ES2018: https://www.ecma-international.org/ecma-262/8.0/index.html
ES2019:極可能也會在今年6月份發佈
與javascript的關係:ECMAScript是一種語言標準,javascript實現了這個標準。javascipt由三部分組成
ECMAScript
DOM
BOM
es6新增了不少強大的語法,以下是比較常使用的:
let 和 const
解構賦值
函數
字符串擴展
數組擴展
新的定義對象的方式
參考:
各類環境中對es6的支持程度: http://kangax.github.io/compat-table/es6/
es5中提供了定義變量的關鍵字var,可是這個關鍵字的功能有限,它定義的變量也有不少奇怪的特性,並不能徹底知足如今愈來愈複雜的環境,因此在es6中新增了兩個關鍵字:let,const。
它用來定義變量,基本使用格式與var關鍵字同樣。在能夠在使用var 的地方改爲let。
不能重複定義
具備塊級做用域
沒有變量提高(var定義的變量是有變量提高的),必須先定義再使用
不會附加到window對象的屬性中
// 1. let 定義變量,變量不能夠再次定義,但能夠改變其值
let name = 'zhangsan';
name = 'lisi';
console.log(name); // lisi
let name = 'wangwu'; // 再次定義,報錯:Identifier 'name' has already been declared
// 2. 具備塊級做用域,塊就是大括號
{
let age = 18;
console.log(age); // 18
}
console.log(age); // 報錯,此做用域中沒有age的定義
for (let i = 0; i < 10; i++) {
// i 只能在此範圍內使用,由於有塊級做用域
}
console.log(i); // 報錯,此做用域中沒有age的定義
// 3. 沒有變量提高,必須先定義再使用
console.log(gender); // 報錯,此時尚未定義gender
let gender = '男';
console.log(1); // 不報錯,輸出undefined
var a = 1;
// 4. let聲明的變量不會壓到window對象中,是獨立的
let hobby = '吃飯';
var a = 1
console.log(window.hobby); // undefined
console.log(window.a); // undefined
若是使用var聲明瞭變量,也不能再次用let聲明瞭,反之也是不行的。緣由也是這個變量已經被聲明過了。
最佳實踐:實際開發要麼所有使用var,要麼所有使用let。由團隊開發規範來定。
多個程序員共同開發項項目時,會遇到一種場景:有一些數據你們都須要用到,可是都不能修改,即數據是隻讀的。
舉個例子:在開發公司的網站時,公司的基本信息:地址,公司名,電話等等信息能夠在多個地方都須要使用,但不容許去修改。 這個時候,就能夠把這些數據保存在常量中。
// 格式:
const 常量名 = 常量值;
const COMPANY_NAME = "XXX公司"
區別於變量名,常量名通常採用全大寫的方式
多個單詞之間使用_劃線分隔。
const obj = {a:1};
obj.a = 2;
console.log(obj); // 問題:obj對象的屬性值a是否修改了。
const實際上保證的,並非變量的值不得改動,而是變量指向的那個內存地址所保存的數據不得改動。
對於簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,所以等同於常量。
對於複合類型的數據(主要是對象和數組),變量指向的內存地址,保存的只是一個指向實際數據的指針,const只能保證這個指針是固定的(即老是指向另外一個固定的地址),至於它指向的數據結構是否是可變的,就徹底不能控制了。所以,將一個對象聲明爲常量必須很是當心,它的屬性是能夠修改的。
具備塊級做用域
沒有變量提高,必須先定義再使用
常量也是獨立的,定義後不會壓入到window對象中,不是window對象的屬性
關鍵字 | 變量提高 | 塊級做用域 | 初始值 | 更改值 | 經過window調用 |
---|---|---|---|---|---|
let | × | √ | - | Yes | No |
const | × | √ | Yes | No | No |
var | √ | × | - | Yes | Yes |
ES 6 容許按照必定模式,從數組和對象中提取值,對變量進行賦值,這被稱爲解構(Destructuring)。
它有兩個動做:
- 解構:意思是把有結構的數據分解開成爲一個一個的值;
- 賦值:把解構以後的值保存到變量。
demo
let arr = [1,2,3,4];
// 需求,快速地從數組中取出值來賦值給變量
let a = arr[0];
它可以快速從數組中取出值保存到變量中。它的本質是給變量賦值。
內容:
語法格式及解構規則
常規使用:變量個數等於數組長值
很是規使用
變量個數大於數組長度
變量個數小於數組長度
高級使用
用空跳過不須要的值
剩餘值
複雜嵌套場景
小面試題
// 格式:
let [變量1,變量2,
// 場景1,變量和值一一對應
let arr = [5, 9, 10];
let [a, b, c] = arr;
console.log(a, b, c); // 輸出 5 9 10
// 等價於:
let a = arr[0];
let b = arr[1];
let c = arr[2];
注意:
「=」左右兩邊的格式要統一。
// 場景2,變量多,值少
let arr = [5, 9, 10];
let [a, b, c, d] = arr;
console.log(a, b, c, d); // 輸出 5 9 10 undefined
// 結論:沒有匹配上的值是undefined
// 場景3,變量少,值多
let arr = [5, 9, 10, 8, 3, 2];
let [a, b] = arr;
console.log(a, b); // 5, 9
// 結論:多餘的忽略
// 場景4,按需取值
let arr = [5, 9, 10, 8, 3, 2];
let [, , a, , b] = arr; // 不須要用變量接收的值,用空位佔位
console.log(a, b); // 10, 3
// 場景5,剩餘值
let arr = [5, 9, 10, 8, 3, 2];
let [a, b,
注意:
... 的收集
Rest element must be last element。必須在最後;
// 場景6,複雜的場景,只要符合模式,便可解構
let arr = ['zhangsan', 18, ['175cm', '65kg']];
let [, , [a, b]] = arr;
console.log(a, b); // 175cm 65kg
交換兩個變量的值?
var a = 1, b = 2;
// 寫代碼,實現互換a,b的值
// ????
console.info(a,b); // 要求輸出 2, 1
做用:快速從對象中獲取值保存到變量中。它的本質是給變量賦值。
也經過以下幾種場景來學習
變量名和屬性名同樣
變量更名
剩餘值
複雜嵌套
完整格式:
let {"屬性名1":變量名1, "屬性名2":變量名2 } = {"屬性名1":屬性值1,"屬性名2":屬性值2,
解析規則:
右邊的"屬性名"與左邊的「屬性名」 一致,則把右邊的屬性值賦值給左邊的變量名。
精簡格式:
若是左側對象中屬性名與變量名相同,則可左側合併:
let {變量名1,變量名2} = {"屬性名1":屬性值1,"屬性名2":屬性值2,
解析規則:
右邊的"屬性名"與左邊的變量名 一致,則把右邊的屬性值賦值給左邊的變量名。
場景1,變量名和屬性名同樣
// 場景1,默認要求變量名和屬性名同樣
let { name, age } = {age: 27, name: '陽明'};
console.log(name, age);
let {a, c} = {a: 'hello', b: 'world'};
console.log(a, c); // hello, undefined
注意:
「=」 左右兩邊的格式一致。
對象是屬性的無序集合,因此不須要管順序
場景2,變量更名
// 場景2,能夠經過:爲變量更名
let {a, b:c} = {name: '王陽明', b: 'world'};
console.log(a, c); // hello, world
// 把其它的屬性全收集起來
let obj = {name:'zs', age:20, gender:'男'};
let {name,
只要符合模式,便可解構
// 複雜的場景,只要符合模式,便可解構
let obj = {
name: 'zhangsan',
age: 22,
dog: {
name: '毛毛',
age: 3
}
};
let {dog: {name, age}} = obj;
console.log(name, age); // 毛毛 3
// 假設從服務器上獲取的數據以下
let response = {
data: ['a', 'b', 'c'],
meta: {
code: 200,
msg: '獲取數據成功'
}
}
// 如何獲取到 code 和 msg
let { meta: { code, msg } } = response;
console.log(code, msg); // 200, 獲取數據成功
es6對函數的功能進行了一些拓展,補充了不少功能。學習這個部分的內容咱們就能夠靈活地使用函數。
內容
參數默認值
箭頭函數(重點)
rest參數
參數默認值是一個很是實用的功能,學習這個部分咱們能夠更加地理解api中的默認參數的實現,能寫出用戶體驗更好的函數。
參數的默認值在以前的課程內容已經涉及,例如在xhr.open(type,url,是否異步)方法中,第3個參數默認是true,即表示異步ajax。
默認值的意思是:
若是傳入,就用你傳的值
若是不傳入,就使用某一個特殊的、事先定義好的值。這個值也就是默認值。
ES6 以前,函數不支持設置參數的默認值(其它大多數編程語言都是支持的)。但雖然在語法層面上不支持,程序員們也會想一些變通的方法。
// ES5 中給參數設置默認值的變通作法
function open(type, url,isAsync) {
if(isAsync === undefined){
isAsync = true;
}
console.log(type, url, isAsync);
}
// 下面這兩句是等價的
open("get","common/get");//
open("get","common/get",true);
open("get","common/get",false);
function 函數名(參數名1='默認值1',參數名2='默認值3',參數名1='默認值3'){
}
// E65 給參數設置默認值
function open(type, url,isAsync=true) {
console.log(type, url, isAsync);
}
思考:可否給type設置默認值,爲'get' ?
function open(type='get', url,isAsync=true)
注意:
帶默認值的形參放在形參列表的後面
let obj1 = { url: "/common/get", type:"get"}
function open(obj){
console.info(obj.url, obj.get)
}
function open({url,type}){
console.info(url,type)
}
function open({url,type='get'}){
console.info(url,type)
}
學習箭頭函數能讓代碼更簡潔,效率更高;能看懂別人寫的代碼 ;
let fn3 = x => x * 2;
內容
定義及格式
三種簡化原則
三個特色
典型應用場景
ES6 中容許使用箭頭函數的方式來定義一個函數。前面學習的定義一個函數有兩種方式:
函數聲明式
函數表達式
如今有了一個新的方式:
3. 箭頭函數
let 函數名 = (形參1,
// 1. 函數聲明式
function fu1(x){
return x * 2;
}
// 2. 函數表達式
let fn2 = function (x) {
return x * 2;
}
// 3. 箭頭函數
let fn3 = (x) => {
return x * 2;
}
第一眼看到這個箭頭函數時,會以爲很奇怪。若是從函數表達式的格式出發, 通過以下2步演化步驟就能夠獲得。
把function 關鍵字 後移動到 ()和 {} 中間
把function 改寫成 =>
注意:
- `=>`是一個總體,不要加空格
- 箭頭函數只在定義上有些區別,但在函數調用格式上,是沒有區別的。
當形參有且只有一個,能夠省略小括號
當函數體只有一條語句,能夠省略大括號;
當函數體只有一條語句,而且就是return語句,則能夠省略return
// 完整箭頭函數
let fn = (x) => {
return x * 2;
}
// 參數只有一個,省略小括號
let fn = x => {
return x * 2;
}
// 函數體中只有一個返回語句,能夠省略大括號
let fn = x => x*2
它與普通函數的區別
內部沒有arguments
內部沒有this
不能做爲構造器
let fn = (a,b) => {
console.log(arguments); // 報錯,arguments is not defined
};
fn(1, 2);
var name = 'lisi'; // 測試時,這裏必須用var,由於用let聲明的變量不能使用window調用 let obj = { name: 'zhangsan', fn : () => { console.log(this); // window對象 console.log(this.name); // lisi } }; obj.fn();
let Person = () => { }; let obj = new Person(); // 報錯,Person is not a constructor // 換個角度理解,箭頭函數中都沒有本身的this,怎麼處理成員,因此不能當構造函數
定義函數
回調函數
事件響應函數
var arr = [1,2,3] arr.sort(function(a,b){ return a - b}); // 簡化 arr.sort((a,b)=>a-b)
rest: 其它的,剩餘的; rest 參數 用於獲取函數多餘參數,把它們放在一個數組中。
在定義函數時,在最後一個參數前面加上..., 則這個參數就是剩餘參數;
let fn = function(參數1,參數2,...rest參數){} let fn = (參數1,參數2,...rest參數)=>{ }
只是在定義函數時,在形參列表中區別一下,而在調用函數時並沒有區別。
回答以下問題
function f1 (x,y){ console.log(x,y) } f1(1,2); f1(2,3,4); function f2 (x,...y){ console.log(x,y) } f2(1,2); f2(2,3,4);
問題:編寫一個函數,求全部參數之和;
方法一:arguments
方法二:rest參數
function getSum (){ // 在這裏寫你的代碼 var sum = 0 ; for(var i = 0; i < arguments.length; i++){ console.info( arguemnts[i]) sum += arguments[i]; } }
若是以箭頭函數 的方式去定義這個函數,則內部不可使用arguments這個對象了。此時,咱們就可使用
rest 參數,它能夠替代 arguments 的使用。 代碼以下:
// 參數不少,不肯定多少個,可使用剩餘參數 const getSum = (...values) => { var sum = 0 ; for(var i = 0; i < values.length; i++){ console.info( values[i]) sum += values[i]; } } // 調用 console.log(fn(6, 1, 100, 9, 10));
數組對象是js中很是重要的對象,它自己提供了很是多的方法:sort,push,pop,unshift, splice,concat.... 。因爲前端的主要工做內容之一是與後端進行數據交互,而數據交互的載體大可能是數組,因此咱們對數組的操做要求也很是高。
曾經有一道面試題:寫出10個你用過的與數組相關的方法。
這一小節的學習會讓咱們多掌握幾個數組的方法。
功能:它的做用是把數組中的元素一項項地展開:把一個總體的數組拆開成單個的元素。
格式:...數組
基本用法
console.info(...[1,2,3]);
應用1: 數組合並
從把一個數組中的值全取出來,放在另外一個數組中的
var arr0 = ['a','b']; var arr1 = [1,2,3]; var arr2 = [4, ...arr1]; var arr3 = [..arr0 ,...arr1];
應用2:Math.max()
Math.max(1,3,4,6); var arr = [1,3,4,6]; Math.max(...arr);
功能:把其它非數組的對象轉成數組。
格式: 數組 = Array.from(非數組對象)
它的實參有三種狀況:
自定義的,特殊格式的對象
let fakeArr = { 0: 'a', 1: 'b', 2: 'c', length: 3 };
arguments對象
DOM 操做返回的 NodeList 集合
在實際的開發中,咱們常常會遇到一種場景:從一個數組中找出符合條件的元素。咱們要的討論的重點是如何從數組中找出符合條件的元素,固然,咱們能夠經過手寫循環的方式來實現這個功能,可是如今es6中提供了現成的功能。find/findIndex
做用:從數組中找出咱們符合條件的第一個元素(或者是下標)。
find和findIndex的格式是一致的。
let result = [].find(function(item,index,self){ //.... // 若是知足查找的條件 return true; })
回調函數有三個參數,分別表示:數組元素的值、索引及整個數組
若是某次循環返回的是true,find和findIndex方法的返回值就是知足這個條件的第一個元素或索引
find和findIndex方法,會遍歷傳遞進來的數組
若是在回調函數體內,某個時刻return true,則表示查找過程結果,返回值就是本輪循環中的元素(或者是下標);若是所有的循環結束,也沒有返回true,則表示沒有找到。
findIndex 找到數組中第一個知足條件的成員並返回該成員的索引,若是找不到返回 -1。
let arr = [1, 2, 4, 0, -4, 3, -2, 9]; arr.find(function (item, index, self) { console.log(item); // 數組中的每一個值 console.log(index); // 數組中的每一個索引/下標 console.log(self); // 當前的數組 });
// 用法:找數組中第一個小於0的數字 let arr = [1, 2, 4, 0, -4, 3, -2, 9]; let result = arr.find(function (item) { return item < 0; //遍歷過程當中,根據這個條件去查找 }); console.log(result); // -4
注意經過箭頭函數來簡化代碼。
從一個複雜的對象數組中找出符合條件的對象。
let data = [ {id:2,name:'嚴高',age:15}, {id:3,name:'徐階',age:17}, {id:4,name:'高拱',age:18}, {id:1,name:'張居正',age:12}, ]
findIndex 的使用和 find 相似,只不過它查找的不是數組中的元素,而是元素的下標。
功能:判斷數組是否包含某個值,返回 true / false
格式:數組.includes(參數1,參數2)
參數1,必須,表示查找的內容
參數2,可選,表示開始查找的位置,0表示從第一個元素開始找。默認值是0。
示例:
let arr = [1, 4, 3, 9]; console.log(arr.includes(4)); // true console.log(arr.includes(4, 2)); // false, 從2的位置開始查,因此沒有找到4 console.log(arr.includes(5)); // false
字符串也有這個方法,功能也是類似的。
es6中對字符串提供了新的特性,咱們介紹其中幾個方法:
模板字符串
includes
startsWith
endWith
repeat
在作字符串拼接時,使用+來拼接複雜內容是很麻煩的,而模板字符串能夠解決這個問題。
格式:`${變量} ${表達式}`
語法:
模板字符串使用反引號 ` 把內容括起來,相似於普通字符串的""。
${}充當界定符的做用,其中能夠寫變量名,表達式等。
容許字符串內部進行換行,代碼更好讀更好的體驗
示例:
let name = 'zs'; let age = 18; // 拼接多個變量,在模板字符串中使用佔位的方式,更易懂 let str = `我是${name},今年${age}`; // 內容過多能夠直接換行 let obj = [{name: 'flex', age: 20},{name: 'james', age: 21}]; let arr = ['175cm', '60kg']; let html = ` <div> <ul> <li>${obj.name}</li> <li>${obj.age}</li> <li>${arr[0]}</li> <li>${arr[1]}</li> </ul> </div>
格式:str.includes(searchString, [position])
功能:返回布爾值,表示是否找到了參數字符串
position: 從當前字符串的哪一個索引位置開始搜尋子字符串,默認值爲0。
格式:str.startsWidth(searchString, [position])
功能:返回布爾值,表示參數字符串是否在原字符串的頭部或指定位置
position: 在 str 中搜索 searchString 的開始位置,默認值爲 0,也就是真正的字符串開頭處。
格式:str.endsWith(searchString, [len])
功能:返回布爾值,表示參數字符串是否在原字符串的尾部或指定位置.
len:可選。做爲 str 的長度。默認值爲 str.length。
repeat方法返回一個新字符串,表示將原字符串重複n次。
語法:str.repeat(n)
let html = '<li>itheima</li>'; html = html.repeat(10);
ES6 將全局方法parseInt()和parseFloat(),移植到Number對象上面,行爲徹底保持不變。
Number.parseInt()
Number.parseFloat()
Set是集合的意思。是ES6 中新增的內置對象,它相似於數組,可是成員的值都是惟一的,即沒有重複的值。使用它能夠方便地實現用它就能夠實現數組去重的操做。
建立空set;
根據已有數組建立set
// 1. 基本使用 let set = new Set(); // 獲得一個空的Set對象 let set = new Set([1,2,3])
size:屬性,獲取 set 中成員的個數,至關於數組中的 length
add(value):添加某個值,返回 Set 結構自己。
delete(value):刪除某個值,返回一個布爾值,表示刪除是否成功。
has(value):返回一個布爾值,表示該值是否爲Set的成員。
clear():清除全部成員,沒有返回值。
遍歷for of
let arr = [1,1,2,3,3]; console.info([...new Set(arr)])
對屬性名的簡化
對方法的簡化
let name = 'zhangsan', age = 20, gender = '女'; let obj = { name: name, // 原來的寫法 age, // 對象屬性和變量名相同,能夠省略後面的 「:age」,下面的gender同理 gender, fn1:function(){ // 常規寫法 console.log(123); }, fn2 () { // 能夠省略 console.log(456); } }; console.log(obj.age); // 20 obj.fn2(); // 456
ES6 (2015年10月)雖好,可是有兼容性問題,IE7-IE11 基本不支持 ES6
在最新的現代瀏覽器、移動端、Node.js 中都支持 ES6
後續咱們會講解如何處理 ES6 的兼容性
由於 ES 6 有瀏覽器兼容性問題,可使用一些工具進行降級處理,例如:babel
降級處理 babel 的使用步驟
安裝 Node.js
命令行中安裝 babel
配置文件 .babelrc
運行
安裝 Node.js
項目初始化(項目文件夾不能有中文)
npm init -y
在命令行中,安裝 babel babel官網
npm install @babel/core @babel/cli @babel/preset-env
配置文件 .babelrc (手工建立這個文件)
babel 的降級處理配置
{ "presets": ["@babel/preset-env"] }
在命令行中,運行
# 把轉換的結果輸出到指定的文件 npx babel index.js -o test.js # 把轉換的結果輸出到指定的目錄 npx babel 包含有js的原目錄 -d 轉換後的新目錄
參考:babel官網