1. 程式人生 > >es6,es7,webpack 和 babel(愛前端)

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 物件   未完。。。