es6,es7,webpack 和 babel(愛前端)
npm install -g cnpm --registry=https://registry.npm.taobao.org
預設安裝位置:
一 ES6, ES7 簡介和除錯方法
1.1 簡介
ECMAScript6 就是ECMAScript2015
ECMAScript7 就是ECMAScript2016
ECMAScript8 就是ECMAScript2017
ECMA組織2015年開始每年都要釋出一個ECMAScript的新版本。
ECMAScript現在的語言實現就兩個:JavaScript、ActionScript。
1.2 瀏覽器除錯
使用新版本的瀏覽器,就能除錯一些 ES6, 7, 8 的語法
在瀏覽器除錯的時候,要有HTML的殼子,要有 script 標籤
1.3 使用 NodeJS 除錯
檢視 node 版本: 命令列 node -v 回車
執行結果:
1.4 使用 Babel 翻譯
-g 安裝的,一般叫做 CLI 程式 , commond line interface 命令列介面,這些命令可以在 CMD 視窗中使用
npm install -g cnpm --registry=https://registry.npm.taobao.org
預設安裝位置:
執行上述程式碼後,我們能在 CMD 中執行 cnpm
1, babel 需要用 -g 安裝
檢查 babel 是否安裝成功: babel --version
2, 到這一步,切換到專案目錄下,建立一個檔案 .babelrc 檔案 rc 表示 resource 資源的意思
windows 下不允許檔名以 . (點) 開頭,解決:先建立一個檔案,然後 rename xx.txt .babelrc
檔案內容:
3 完成 .babelrc 之後,還要安裝這個 preset 的依賴
cnpm install --sava-dev babel-preset-es2015
--save-dev表示在專案的 package.json 檔案中的“devDependencies”欄位列出,表示專案的開發依賴。
就是說是在專案開發的時候,用的翻譯器、打包工具、構建工具等等
ps: 預設 babel 不認識 ... 語法 ,會報錯,要裝外掛,讓 babel 識別更多的語法
babel 的外掛在 npm 庫中都叫做 babel-plugin-***
淘寶 NPM 映象: https://npm.taobao.org/
4 裝外掛 npm install --save-dev @babel/plugin-syntax-object-rest-spread
更改 .babelrc 檔案,告訴 babel 我們要求你使用外掛:
5 現在可以用 babel 命令進行翻譯
babel 02.js -o 0200.js
二 const 和 let
2.1 const 阮一峰的部落格
const宣告一個只讀的常量。一旦宣告,常量的值就不能改變。通常用 const 定義函式。
函式的定義一般來說都是不變的,所以今後的函式一律用 const 定義
const sum = function(a,b){
return a + b;
}
console.log(sum(2,3));
const A = 12;
A = 8; // 報錯
一般來說所有字母要大寫
2.2 let
let 用來定義塊級作用域變數。它的用法類似於 var,但是所宣告的變數,只在 let 命令所在的程式碼塊內有效。
所謂的塊級作用域指的是大括號、所有的語句體。
{
var a = 1;
}
console.log(a); //能夠輸出1
{
let b = 2;
}
console.log(b); //報錯
var定義的變量出了 { } 依然有定義,但是 let 出了 { } 沒有定義了
今後,我們的所有的迴圈變數將用let來定義:
需要注意:
1) 不管是 let 還是 const,都沒有了變數宣告的提升;
console.log(m); //報錯,沒有變數宣告的提升;
let m = 100;
2) 不管是 let 還是 const,babel 一律翻譯為 var。
三 變數的自動解構和剩餘引數
3.1 自動解構
只有陣列和物件能夠自動解構。
ES6中允許從陣列中提取值,按照對應位置,對變數賦值。物件也是一樣的。
陣列的解構 |
物件的解構 |
var [a,b,c] = [1,2,3]; console.log(a); console.log(b); console.log(c); |
這裡是 { } |
物件的解構往往用在函式的形參列表中,呼叫函式的時候,傳的物件(實參)就能夠自動解構。
1 function People({name,age,sex,yuwen,shuxue,yingyu}){
2 this.name = name;
3 this.age = age;
4 this.sex = sex;
5 this.yuwen = yuwen;
6 this.shuxue = shuxue; 7 this.yingyu = yingyu; 8 } 9 var xiaoming = new People({ 10 "name" : "小明", 11 "age" : 12, 12 "sex" : "男", 13 "yuwen" : 34, 14 "shuxue" : 44, 15 "yingyu" : 66 16 }); 17 18 console.log(xiaoming);
3.2 剩餘引數
在 c 變數之前加上...運算子,表示 c 現在接受所有剩餘的引數
需要注意的事情是:... 只能出現在最後一項 ,下面寫法是錯的
var [a,...b,c] = [1,2,3,4,5,6,7];
let {x, y, ...z} = {x:1, y:2, a:3, b:4};
console.log(x); // 1
console.log(y); // 2
console.log(z); // {a:3, b:4 }
let n = {x,y,...z};
console.log(n); // {x:1, y:2, a:3, b:4}
3.3 強制解構
在陣列前面加上 ... 運算子,表示強制解構。這個陣列將變為零散量
1 var arr = [1,3,32];
2 console.log(...arr); // 1 3 32
3
4 var str = [...arr];
5 console.log(str); // [ 1 3 32 ]
... 運算子也可以作用於物件,通常用於一個情況:建立 obj1 的副本,僅僅改變 obj1 的某一(些)個屬性
1 var obj1 = {
2 "a" : 1,
3 "b" : 2,
4 "c" : 3
5 };
6
7 var obj2 = {
8 ...obj1 , 9 "b" : 8 10 }; 11 12 console.log(obj2);
執行結果:
強制解構還可以用於類陣列物件,可以將類陣列物件變為真的陣列
1 const fun = function(){
2 //下面的語句是一個奇淫技巧,是最快的將類陣列物件變為陣列的方法
3 var arr = [...arguments];
4 console.log(arr); //[ 1, 2, 3, 4, 5, 6, 7, 8 ]
5 console.log(Array.isArray(arr)); //true
6 }
7 fun(1,2,3,4,5,6,7,8);
如果用 babel 解構物件,需要安裝 babel 的外掛 babel-plugin-transform-object-rest-spread
四 陣列的新方法
4.1 forEach 遍歷陣列
4.2 map()
map() 返回一個新的陣列,新陣列的每一項是原陣列的對映
例:是建立一個數組,每一項都是原來的陣列的兩倍
var arr = [12,432,2,25,6];
var newArr = arr.map(function(item){
return item*2;
});
console.log(newArr);
注意:map() 出的陣列,一定和原陣列長度相同!
函式裡面的的return就是新陣列中這一項的數值
4.3 filter()
例:從一個數組中,過濾一些項組合成新陣列,此時使用 filter() 函式
var arr = [12,432,2,25,6];
var arr2 = arr.filter(function(item){
return item %2 == 0;
});
console.log( arr2); // [ 12, 432, 2, 6 ]
filter() 中有一個函式,這個函式 return 為 true 的項會被加入到新的陣列中
例:再比如從一個數組中,提取所有及格組合成為新陣列
var arr = [
{"name":"小明" , "fenshu" :66},
{"name":"小紅" , "fenshu" :16},
{"name":"小強" , "fenshu" :26},
{"name":"小剛" , "fenshu" :86}
];
var arr2 = arr.filter(function(item){ return item.fenshu >= 60; }); console.log(arr2);
結果:
4.4 reduce()
reduce 表示迭代遍歷,每一項的遍歷都可以使用遍歷上一項的時候的結果。
reduce可以理解為“降階”。
reduce裡面的函式有兩個引數,分別是a、b。
我們來探究 a、b 什麼意思。所以我們直接輸出a:
var arr = ["白板","么雞","二條","三萬","四筒"]; arr.reduce(function(a,b){ console.log(a); }); |
var arr = ["白板","么雞","二條","三萬","四筒"]; arr.reduce(function(a,b){ console.log(b); }); |
少一項 |
reduce的機理:
l a 就表示遍歷前一項的時候 return 的值,b 表示這一項的值。
l 系統會自動從下標為1的項開始遍歷,遍歷下標為1的項的時候,a 的值是第0項。
l 最後的一項的 return,就是總 return。
4.5 綜合運用 map() , filter() , reduce() , 解構 (重要)
例:
var xiaoming = { "name" : "小明", "age" : 12, "sex" : "男", "friends" : [ { "name" : "小紅", "age" : 13 }, { "name" : "小強", "age" : 14 }, { "name" : "小剛炮", "age" : 18 } ] }
題目1: 不允許更改小明,返回一個新物件,這個物件和小明相同,僅讓小明的年齡變為 15歲
題目2:不允許更改小明,讓小強的 age 變為 12
var xiaoming1 = {
...xiaoming, // 解構
'friends': xiaoming.friends.map(function(item){
if(item.name =='小強'){
return {
...item, // 解構
'age': 22 // 修改為 22
}
}
return item; }) } console.log(xiaoming1);
題目3: 不允許更改小明,讓小明只有 15 歲以下的朋友
var xiaoming1 = {
...xiaoming,
'friends': xiaoming.friends.filter(function(item){
return item.age < 15; // 條件 年齡小於15歲
})
}
題目4:不允許更改小明,小明增加一個朋友, 老王,29歲
var xiaoming1 = {
...xiaoming,
'friends': [...xiaoming.friends,{
'name': '老王',
'age' : 29
}]
}
題目5:不允許更改小明,增加一個朋友,並且自動編號
在題目上,給每個 friends 新增 id
var xiaoming1 = {
...xiaoming,
'friends' : [
...xiaoming.friends,
{
'id' : xiaoming.friends.reduce(function(a,b){
return a.id > b.id ? a : b; // 返回 id 大的一個
}).id + 1, // +1
'name' : '老王',
'age' : 29
}
]
}
不更改原來的物件,返回一個新物件,新物件是原來物件的增、刪、改某些屬性,這叫做函數語言程式設計,也叫作蘭姆達式程式設計
刪除用 filter
改變用 map
增加用 ...
作業:
var canting = {
"name" : "全聚德",
"cai" : {
"liangcai" : [
{
"name" : "涼拌西紅柿",
"price" : 15 }, { "name" : "拍黃瓜", "price" : 18 } ], "recai" : [ { "name" : "宮保雞丁", "price" : 25 }, { "name" : "紅燒肉", "price" : 45 }, { "name" : "辣子雞", "price" :15 } ] } } // 宮保雞丁 不賣了 var c = { ...canting, 'cai' : { ...canting.cai, 'recai' : canting.cai.recai.filter(function(item){ return item.name != '宮保雞丁'; }) } } // 宮保雞丁 更改價格 var c = { ...canting, 'cai' : { ...canting.cai, 'recai' : canting.cai.recai.map(function(item){ if(item.name == '宮保雞丁'){ return { ...item, 'price' : 30 } } return item; }) } } // 增加一個新菜:紅燒茄子,19元 var c = { ...canting, 'cai' : { ...canting.cai, 'recai' : [...canting.cai.recai,{ 'name' : '紅燒茄子', 'price' : 19 }] } } // 售價 20 以上的熱菜都不賣了 var c = { ...canting, 'cai' : { ...canting.cai, 'recai' : canting.cai.recai.filter(function(item){ return item.price <= 20 }) } } console.log(JSON.stringify(c)); // console.log(c) 不能全部顯示出來
//學習這個很關鍵,比如react的元件中有state(狀態):
this.state = {
a : 1,
b : [5,6,7,8],
c : 3
};
//修改的時候,不能更改原來的state。比如我們要把9加入到b屬性中,正確:
this.setState({
b : [...this.state.b , 9] });
4.6 includes() 方法
Array.prototype.includes 方法返回一個布林值,表示某個陣列是否包含給定的值。
之前我們判斷陣列中是否存在一項,此時用 indexOf() != -1(IE8開始相容)。如果要IE6、7相容,必須一項一項遍歷比較。
ES6中,有了更簡單的比較方法
注意,includes是全等比較,帶著型別比較的 7 ‘7’
4.7 Array.from() 方法
Array.from 方法用於將類陣列轉為真正的陣列
結果:
五 物件的改變
5.1 省略 v
當一個物件的 k、v 相同(k 的名字和 v 的變數名相同),此時可以省略v
比如下面有三個變數a、b、c,要作為一個物件的屬性名a、b、c,同時值也是1、2、3。
因為k、v一致,此時就可以省略v
結果:
注意,省略 v 的時候,k 不能有引號!
5.2 物件的方法現在可以簡寫
5.3 Object.keys() 和 Object.values()
Object.keys() 返回物件的鍵名陣列;
Object.values() 返回物件的值陣列;
結果:
5.4 Object.is()
ES5 比較兩個值是否相等,只有兩個運算子:相等運算子(==)和嚴格相等運算子(===)。
它們都有缺點,前者會自動轉換資料型別,後者的 NaN 不等於自身,以及+0等於-0。
JavaScript 缺乏一種運算,在所有環境中,只要兩個值是一樣的,它們就應該相等
5.5 Object.assign()
Object.assign 方法用於物件的合併,將源物件(source)的所有可列舉屬性,複製到目標物件(target)。
結果:
注意 Object.assign() 可以有無限個引數,但是隻會更改第一個引數物件
5.6 物件中鍵加方括號 -- 動態鍵
var sex = '女';
if(sex == '男'){ // 值判斷
var k = '身高';
} else {
k = ' 視力';
}
var obj = {
'name': 'rose', 'sex' : sex, [k] : 'xxx' // 動態鍵 } console.log(obj);
六 函式的改變
6.1 箭頭函式
下面的sum就是標準的箭頭函式,省略掉了function這個關鍵字:
=>是一個完整的運算子,之間不能有空格
如果函式體內只有一行語句,可以省略 {} 和 return
反過來,如果函式體內有多條語句,此時必須寫 {} 和 return 單詞
箭頭函式的美,最能體現在連續箭頭。當外層函式被呼叫的時候,將返回內層的函式。呼叫的時候可以加兩層圓括號
箭頭函式中的 this 是定義時所處的上下文,和如何呼叫無關!
比如下面有一個 obj 物件,這個物件的 b 方法是用箭頭函式寫的。這個箭頭函式所在的最外層函式體是 window 域。
所以 this 不管 b 函式如何被呼叫,一律是 window 物件
var a = 9;
var obj = {
a : 1 ,
b : () => { // 箭頭
console.log(this.a);
}
}
obj.b(); //9 這裡不能用 node 解析, window 物件
甚至call、apply失效:
this 在箭頭函式中是固定的,這個性質是我們應該防止的、加以警惕的;而不是利用的
箭頭函式有幾個使用注意點。
(1)函式體內的this物件,就是定義時所在的物件,而不是使用時所在的物件。
(2)不可以當作建構函式,也就是說,不可以使用new命令,否則會丟擲一個錯誤。
(3)不可以使用arguments物件,該物件在函式體內不存在。如果要用,可以用 rest 引數代替。
(4)不可以使用yield命令,因此箭頭函式不能用作 Generator 函式。
6.2 bind()
bind表示給一個函式定死上下文,而無論它如何被呼叫。
比如下面有一個函式 fun,函式體輸出 this.a。
我們在後面有一個 .bind() 語句,徹底將 fun 函式的上下文定死了,就是 obj 物件。
無論 fun 函式如何被呼叫,一律上下文是 obj 物件。
function fun(){
console.log(this.a);
}
//這是一個物件
var obj = {
a : 233 ,
b : 886
}
//這是另一個物件
var another = { a : 6666666666666 } //定死上下文為obj物件 fun = fun.bind(obj); fun(); //233 fun.call(another); //233,call失效了 fun.apply(another); //233,apply失效了
bind 和 call 和 apply 有什麼區別?
l bind 不呼叫函式,call 和 apply 會呼叫函式。
l bind 能綁死上下文,call 和 apply 是臨時的。
6.3 預設引數
在形參列表中可以加等號運算子,表示引數的預設引數,當我們沒有傳入這個引數的時候,
將自動使用這個預設引數
const mianji = (r , pi = 3.14) => {
return pi * r * r;
}
console.log(mianji(10 , Math.PI)); //傳了第二個引數,就是用第二個引數
console.log(mianji(10)); //沒有第二個引數,將用預設的3.14
七 字串, 正則改變
``是新增的定界符,可以和 ${變數} 使用,減少連字元的使用:
八 類的改變
現在可以用 class 關鍵字來定義一個類,語法:
雖然增加了 class 關鍵字,但是 JS 中還是沒有類!JS 中仍然是簡單的“基於物件”原型鏈的模式來模擬類的。
也就是說,機理沒有變化!
ES6 中簡化了類的繼承:
class People{
constructor(name , age , sex){
this.name = name;
this.age = age;
this.sex = sex;
}
changge(){
console.log("我是一個" + this.name + "今年" + this.age + "歲啦!!");
}
}
class Student extends People{
constructor(name , age , sex , xuehao , banji){
super(name , age , sex); //呼叫超類的構造器
this.xuehao = xuehao; this.banji = banji; } kaoshi(){ console.log(`${this.name}在考試`); } } var xiaohua = new Student("小花",12,"女",10001,"1班"); xiaohua.changge(); xiaohua.kaoshi();
九 promise 物件 未完。。。