ES6 學習筆記

一、ECMAScript 6

1. Babel 轉碼器

1.1簡介

Babel 是一個廣泛使用的 ES6 轉碼器,可以將 ES6 代碼轉為 ES5 代碼

1.2babel 安裝和配置

1. 安裝babel
npm init -y 初始化package.json
npm i -D @babel/core
2. 安裝規則集
    npm i -D @babel/preset-env   // es6->es5的規則集
3. 創建配置文件
    .babelrc文件
    {
        "presets":[
            "@babel/env"
        ]
    }

1.3 命令行運行

1. 安裝命令行工具@babel/cli
    npm i -D @babel/cli
2. 語法
    npx babel target.js / -o buidle.js / -d dir

2.let

2.1 簡介

ES6 新增了let命令,用來聲明變量。它的用法類似於var,但是所聲明的變量,只在let命令所在的代碼塊內有效

2.2 用法:

    let num = 12;

2.3 let塊級作用域

    在es6中,只有出現{},就會產生作用域,let聲明的變量如果在{}中,那麼這個變量就是局部變量
    如果let聲明的變量出現在for循環中,這個變量也是局部變量,只能在for循環的大括號中使用

2.4 不存在變量提升

console.log(str);
let str='';
//出現"Cannot access 'str' before initialization"報錯信息,
//說明使用變量在前,聲明變量在後

2.5 不允許重複聲明

let str='';
let str='123';
//出現"Identifier 'str' has already been declared"報錯信息,說明變量重複聲明了

2.6 暫時性死區

    var count = 1;
    {
        console.log(count);
        let count = 3;
    }
    //這時會報錯,報錯信息是"先使用變量,後聲明變量"。

2.7 頂層對象的屬性

  • ES6 為了改變這一點,一方面規定,為了保持兼容性,var命令和function命令聲明的全局變量,依舊是頂層對象(window)的屬性;
  • 另一方面規定,let命令、const命令、class命令聲明的全局變量,不屬於頂層對象(window)的屬性。

2.8 globalThis 對象

  • 全局環境中,this會返回頂層對象。但是,Node 模塊和 ES6 模塊中,this返回的是當前模塊。
  • 函數裏面的this,如果函數不是作為對象的方法運行,而是單純作為函數運行,this會指向頂層對象。但是,嚴格模式下,這時this會返回undefined

3. const

3.1 簡介

const聲明一個只讀的常量,一旦聲明,常量的值就不能改變。

3.2 用法

    const url = '//localhost:8080'

3.3 一旦聲明,常量的值就不能改變

const url='http';
const url='//localhost:8080';//報錯
console.log(url);
//修改值時,會報錯:Assignment to constant variable

const obj={
    user:'fct'
}
obj.user='lllui';//不報錯
console.log(obj);
//如果常量保存是一個對象,那麼這個常量其實只保存了一個地址,和對象中的具體內容沒關係

3.4 let的幾個特點,const全都有

4. 變量的解構賦值

4.1 簡介

ES6 允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱為解構(Destructuring)。

4.2 數組解構賦值:

定義變量的結構和目標數組的結構一致,那麼對應位置的變量就能獲取到對應位置的值。

// 1.數組
let arr=[1,2,3,4];
let [b1,b2,b3]=arr;
console.log(b1,b2,b3);//1 2 3

let arr3 = [1,[2,3,[4,5,6,[7,8,9,[10]]]]];
// 3,5,9,10
let [,[,d1,[,d2,,[,,d3,[d4]]]]] = arr3
console.log(d1,d2,d3,d4);

// 2.數組解構賦值--默認值
let [f=2]=[];
console.log(f);//2

/* 3. rest參數
    語法:[a1,...rest] = [1,2,3,4,5]
    作用:獲取匹配後剩餘的所有元素*/
let [a1,...rest] = [1,2,3,4,5];
console.log(a1,rest);//1 ,[ 2, 3, 4, 5 ]

4.3 對象的解構賦值:

定義變量名稱和對象中的屬性名一致,那麼就能獲取到對應屬性名的值。

// 1. 對象解構賦值-------------------------------
let obj={
    user:'fct',
    age:'21',
    sex:'sex'
}
let {age,sex,user,tel}=obj;
console.log(user,age,sex,tel);//fct 21 sex undefined

// 2. 解構也可以用於嵌套結構的對象
let obj2 = {
    info: {
        tel: '123',
        address: 'xx'
    }
};
//2.1 info是模式,不是變量因此不會被賦值
let { info: { tel, address }} = obj2;
console.log(tel, address);//123 xx
console.log(info);//info is not defined
//2.2 取info
let { info , info: { tel, address }} = obj2;
console.log(tel, address);//123 xx
console.log(info);//{ tel: '123', address: 'xx' }

//3. 修改變量名, uname:uname1---------(同名對象屬性)
let obj3 ={
    uname:'kevin',
    friends:{
        1:{
            uname:'lily'
        },
        2:{
            uname:'lucy'
        }
    }
};
// 3.1 修改friends變量名
let {friends:py}=obj3;
console.log(py);//{ '1': { uname: 'lily' }, '2': { uname: 'lucy' } }
// 3.2 模式,friends是模式
let {friends:{1:{uname}}}=obj3;
console.log(uname);//lily
// 3.3 想獲取lily和lucy兩個人名
let {uname:uname1,friends:{1:{uname:uname2},2:{uname}}} = obj3;

/* 修改變量名和匹配路徑上的模式的區別
    uname:uname1
    如果uname就是最終想獲取的值,uname1就是修改變量名;
    uname:{xxxxx} 
    如果uname是最終想獲取值的路徑上的名稱,uname就是模式*/

// 4.默認值
let { a = 2 } = {
    
};
console.log(a);//2

// 5. ...rest參數
let { a = 2, ...rest } = { a: 1, b: 2, c: 3 };
console.log(a, rest);//1 { b: 2, c: 3 }
//例題:解構對象賦值
let obj4 = {
    name: '電腦',
    main: [
        {
            name: '電源',
            pinpai: 'xx電源'
        }, {
            name: 'CPU',
            pinpai: 'YYCPU'
        }
    ],
    peijian: [
        {
            name: '鍵盤',
            pinpai: '羅技'
        }, {
            name: '鼠標',
            pinpai: '雷蛇'
        }
    ]
}
// 取出所有的name的值
let {name:name1,main:[{name:name2},{name:name3}],peijian:[{name:name4},{name:name5}]}=obj4;
console.log(name1,name2,name3,name4,name5);//電腦 電源 CPU 鍵盤 鼠標

4.4 函數的參數也可以使用解構賦值

//1. 形參解構賦值
function demo([a1,a2,a3,a4,a5]){
    console.log(a1,a2,a3,a4,a5);
}
demo([1,2,3,4,5]);//1 2 3 4 5

function demo2({a:first,b}){
    console.log(first,b);
}
demo2({a:1,b:2});//1 2

function demo3({a,...obj}){
    console.log(a,obj);
}
demo3({a:1,b:2,c:3});//1 { b: 2, c: 3 }

//2. 實參解構賦值
function demo4(a,b){
    console.log(a,b);
}
let obj={
    author:'fct',
    id:244,
    url:'//',
    title:'標題',
    desc:'描述內容'
}
let {author,desc}=obj;
demo4(author,desc);//fct 描述內容

// 3.默認值
function demo5({ a = 5, b = 6 } = {}) {
    console.log(a, b);
}
demo5();//5 6
demo5({});//5 6
demo5({ a: 2 });//2 6

5. 字符串拓展

5.1 模板字符串

定義字符串的新的方式,這種方式中可以隨意換行,可以寫變量,這個變量也可以直接被解析

//模板字符串:
let obj={
    str1:'舉頭望明月,'
}
let str2='低頭思故鄉。'
let str=`
    床前明月光,
    疑是地上霜。
    ${obj.str1}
    ${str2}`;
console.log(str);
/*
    床前明月光,
    疑是地上霜。
    舉頭望明月,
    低頭思故鄉。
*/

6. 數組擴展

6.1 擴展運算符

6.1.1 語法:

...arr

// 1.擴展運算符
let arr=[1,2,'a','b',true];
console.log(arr);//[ 1, 2, 'a', 'b', true ]
console.log(...arr);//1 2 a b true

6.1.2 作用:

​ 能把數組中的元素直接釋放出來,成為一個個的值
6.1.3 應用場景:

  1. 替代函數的 apply 方法

    let arr=[1,2,'a','b',true];function demo(a,b,c,d,e){    console.log(a,b,c,d,e);}demo.apply(this,arr);//1 2 a b truedemo(...arr);//1 2 a b true
    
  2. 複製數組 或 複製對象

    // 2.1複製數組
    let arr2=[1,{name:'keli'},3];
    let arr3=[...arr2];
    arr2[1].name='lilei';
    arr2[0]=666;
    // 淺拷貝,地址引用還在
    console.log(arr2);//[ 666, { name: 'lilei' }, 3 ] 
    console.log(arr3);//[ 1, { name: 'lilei' }, 3 ]
    
    //2.2 複製對象
    let obj3={
        name:'fct',
        age:'22'
    }
    let obj4={...obj3};
    console.log(obj4);//{ name: 'fct', age: '22' }
    
  3. 合併數組或對象

    //合併對象
    let obj={
        a:1,
        b:2,
        c:3
    }
    let obj2={
        d:4
    }
    obj2={...obj2,...obj};//合併對象
    console.log(obj2);//{ d: 4, a: 1, b: 2, c: 3 }
    
  4. 擴展運算符和rest參數有一個顯著的區別

    1.擴展運算符 永遠 出現等號的 右邊,或者直接使用。

    let obj4={...obj3};
    

    2.rest參數一般都在等號的左邊

    let { a , ...rest } = { a: 1, b: 2, c: 3 };
    console.log(a, rest);//1 { b: 2, c: 3 }
    
  5. 實現了 Iterator 接口的對象

    //將類數組都可以用擴展運算符轉為真正的數組let divList=document.querySelectorAll('div');let divArr=[...divList];//例2:function demo2(){    console.log(arguments);//[Arguments] { '0': 1, '1': 2, '2': 3, '3': 45 }    console.log([...arguments]);//[ 1, 2, 3, 45 ]}demo2(1,2,3,45);
    
  6. Map 和 Set 結構,Generator 函數
    原生具備 Iterator 接口的數據結構如下。
    Array
    Map
    Set
    String
    TypedArray
    函數的 arguments 對象
    NodeList 對象

6.2 Array.from()

Array.from(): 將類數組轉化為真實的數組

Array.from方法用於將兩類對象轉為真正的數組:類似數組的對象(array-like object)和可遍歷(iterable)的對象(包括 ES6 新增的數據結構 Set 和 Map)。

let obj5={
    0:'a',
    1:'b',
    2:'hello',
    length:3
}
// let arr4=[...obj5];//報錯,沒有部署Iterator接口
let arr4=Array.from(obj5);//成功
console.log(arr4);//[ 'a', 'b', 'hello' ]

6.3 Array.of()

用於將一組值,轉換為數組

let arr5=Array.of(1,2,3,4);
console.log(arr5);//[ 1, 2, 3, 4 ]

let arr6=new Array(3);
console.log(arr6);//[ <3 empty items> ]

6.4 fill()

使用給定值,填充一個數組

let arr7=new Array(5).fill(3);
console.log(arr7);//[ 3, 3, 3, 3, 3 ]

7.對象的擴展

7.1 屬性的簡潔表示法

ES6 允許在大括號裏面,直接寫入變量和函數,作為對象的屬性和方法

let x=10;
let obj={
    // x:x
    x,// 屬性簡潔表示法
    fn(a,b){//函數簡潔表示
        console.log(a,b);
    }
}
console.log(obj);//{ x: 10, fn: [Function: fn] }

7.2 屬性名表達式

ES6 允許字面量定義對象時,把表達式放在方括號內,作為對象的屬性名

let str = 'uname';
function myage(){
    return 'age';
}
let obj3 ={
    [str]:'kevin',
    [myage()]:12
}
console.log(obj3);//{ uname: 'kevin', age: 12 }

7.3 對象新增的方法

1. Object.is()

在所有環境中,只要兩個值是一樣的,它們就應該相等
它用來比較兩個值是否嚴格相等,與嚴格比較運算符(===)的行為基本一致。
不同之處只有兩個:一是+0不等於-0,二是NaN等於自身。

Object.is('foo','foo');//true
Object.is({},{});//false

+-0===-0;//true
NaN===NaN;//false
Object.is(+0,-0);//false
Object.is(NaN,NaN);//true
2. Object.assign()

Object.assign方法用於對象的合併,將源對象(source)的所有可枚舉屬性,複製到目標對象(target)

// Object.assign()
let target={};
let newObj=Object.assign(target,{a:1},{b:'cc',c:'er'},{d:4});
console.log(target);//{ a: 1, b: 'cc', c: 'er', d: 4 }
console.log(newObj);//{ a: 1, b: 'cc', c: 'er', d: 4 }

對象的每個屬性都有描述對象(Descriptor),用於控制該屬性的行為

Object.defineProperty( obj , key ,{
value : ‘值’,
writable : true, //可寫
enumerable : true, //可枚舉性
configurable : true // 是否可配置
})

0bject.assign():忽略enumerable為false的屬性,只拷貝對象自身的可枚舉的屬性。

Object.getOwnPropertyDescriptor(obj,’key’),方法可以獲取該屬性的描述對象

3.Object.keys(),Object.values(),Object.entries()
  • Object.keys():獲取對象的鍵名
  • Object.values():獲取對象中的鍵值
  • Object.entries():成員是參數對象自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵值對數組

8.Promise 期約

8.1 簡介

Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。

有了Promise對象,就可以將異步操作以同步操作的流程表達出來,避免了層層嵌套的回調函數。

所謂Promise,簡單說就是一個容器,裏面保存着某個未來才會結束的事件(通常是一個異步操作)的結果。Promise 提供統一的 API,各種異步操作都可以用同樣的方法進行處理。

8.2 使用

//Promise 是一個構造函數,使用時new
let p = new Promise(function(resolve,reject){
    // 異步
    resolve(data) // 保存請求成功時的結果
    reject(err)   // 保存請求失敗是的錯誤信息
});

//把Promise容器中保存的結果拿出來
p.then(function success(data){

    },function error(err){

    })

8.3 網絡請求工具

fetch (es6 內置的新的網絡請求方式)

axios (ajax)

8.4Promise 三個狀態

1、pending——–[待定]————–初始狀態
2、resolved——[實現]—————-操作成功
3、rejected—–[被否決]————-操作失敗

當promise狀態發生改變,就會觸發then()里的響應函數處理後續步驟;
promise狀態一經改變,不會再變。
Promise對象的狀態改變,只有兩種可能:
從pending變為resolved
從pending變為rejected。
這兩種情況只要發生,狀態就凝固了,不會再變了

8.5 Promise.proptotype.then()

  • then()方法返回的是一個新的Promise實例(注意,不是原來那個Promise實例)。因此可以採用鏈式寫法,即then方法後面再調用另一個then方法。

  • then()方法中如果沒有顯式的寫return,就會默認return undefined

  • then()方法中的return 後是一個具體的值,那麼promise會直接把這個結果保存到成功狀態中

  • then()方法中return後自己寫new Promise,最終的狀態就和你寫的new Promise返回結果有關

8.6 Promise.prototype.catch()

.catch() = .then(null,function(err){})
//捕獲Promise錯誤的信息

8.7 Promise.prototype.finally()

不管Promise是成功了還是失敗了,這個方法一定會執行

8.8 Promise.prototype.all()

  • Promise.all()方法用於將多個 Promise 實例,包裝成一個新的 Promise 實例

  • 語法:

    let p=Promise.all([p1,p2,p3]);
    p.then((data)=>{
      conlose.log(data);//輸出數據集合
    })
    
  • 返回值:

    1. 當p1,p2,p3都成功時,能獲取到這個三個promise的成功結果,組成一個數組
    2. 當這三個promise有任意一個失敗,Promise.all就返回失敗結果

8.9 Promise.race()

  • Promise.race()方法同樣是將多個 Promise 實例,包裝成一個新的 Promise 實例,只要p1、p2、p3之中有一個實例率先改變狀態,p的狀態就跟着改變。

  • 語法:

    let first=Promise.race([p1,p2,p3]);
    first.then((data)=>{
      conlose.log(data);//獲取最先改變狀態的期約Promise
    })
    
  • 返回值:
    只要p1、p2、p3之中有一個實例率先改變狀態,p的狀態就跟着改變。

8.10 Promise.resolve()

​ 簡寫:resolve()

​ 把promise的狀態設置成功狀態

8.10 Promise.reject()

​ 把promise的狀態設置失敗狀態

8.11 Promise.allSettled()

  • 接受一組 Promise 實例作為參數,包裝成一個新的 Promise 實例。只有等到所有這些參數實例都返回結果,不管是fulfilled還是rejected,包裝實例才會結束。

  • 語法

    let results=Promise.allSettled([p1,p2,p3]);
    results.then((data)=>{
        console.log(data);//Promise數據數組
    })
    

9.Generator(了解)

  • Generator 函數是 ES6 提供的一種異步編程解決方案,語法上,首先可以把它理解成,Generator 函數是一個狀態機,封裝了多個內部狀態,執行 Generator 函數會返回一個遍歷器對象,可以依次遍歷 Generator 函數內部的每一個狀態.

  • 語法:
    Generator 函數是一個普通函數,但是有兩個特徵。一是,function關鍵字與函數名之間有一個星號;二是,函數體內部使用yield表達式,定義不同的內部狀態(yield在英語里的意思就是「產出」)。

  • 執行Generator後返回值是遍歷器對象,這個對象上有一個方法next(),調用這個方法才能執行Generator 函數內部的每一個狀態.

  • next()方法的返回值
    next方法返回一個對象,它的value屬性就是當前yield表達式的值hello,done屬性的值false,表示遍歷還沒有結束

    //Generator 函數
    function* hello(){
        yield 'hello',
        yield 'world',
        yield 1;
        yield 2;
        yield 'fct';
    }
    let it=hello();//生成遍歷器對象
    
    console.log(it);//hello {<suspended>}
    console.log(it.next());//{value: "hello", done: false}
    console.log(it.next());//{value: "world", done: false}
    console.log(it.next());//{value: 1, done: false}
    console.log(it.next());//{value: 2, done: false}
    console.log(it.next());//{value: "fct", done: false}
    console.log(it.next());//{value: undefined, done: true}
    
  • co庫

快速執行Generator函數

10.Async 函數

10.1 簡介

​ 是 Generator 函數的語法糖(新語法), 理解async = Generator + co

await 也是狀態機,只有await後的代碼執行完成,才能向後執行,await還能執行promise.then()方法

10.2 語法

//語法:
async function demo(){
    await 1;
    await 2;
}
//調用
demo();

10.3 使用

async function demo(){
    let a=await 1;
    let b=await 2;
    let c=await 'fct';
    return a+'-'+b+'-'+c;
}
console.log(demo());//Promise { <pending> }---返回值是Promise對象
demo().then((data)=>{
    console.log(data);//   1-2-fct
    // 無return ,值為  undefined
})

10.4 優點

  1. 內置執行器
  2. 更好的語義
  3. 更廣的適用性
  4. 返回值是 Promise

10. 5 錯誤捕獲

  • async函數返回一個 Promise 對象
  • Promise 對象的狀態變化:默認的,async函數返回的 Promise 對象,必須等到內部所有await命令後面的 Promise 對象執行完,才會發生狀態改變,除非遇到return語句或者拋出錯誤。
  • 任何一個await語句後面的 Promise 對象變為reject狀態,那麼整個async函數都會中斷執行,則reject的參數會被catch方法的回調函數接收到

10.6 await命令

  • 正常情況下,await命令後面是一個 Promise 對象,返回該對象的結果值。
  • 如果不是 Promise 對象,就直接返回對應的值。

11. 函數擴展

11.1 函數參數的默認值

// es6 函數參數默認值
function demo(a=1,b=3){
    console.log(a+b);
}
demo();//1+3=4
demo(2);//2+3=5
demo(4,6);//4+6=10

// 參數是數組
function demo2([a=1,b=2]=[]){
    console.log(a+b);
}
demo2();//3
demo2([5]);//7
demo2([5,4]);//9

// 參數是對象
function demo3({a=3,b=6}={}){
    console.log(a+b);
}
demo3();//9
demo3({a:1});//7
demo3({b:2});//5
demo3({num1:1,num2:2});//9

11.2 rest參數

ES6 引入 rest 參數(形式為…變量名),用於獲取函數的多餘參數
注意:rest參數必須放在函數形參的最後一位

// rest參數function demo4(a,b,...abc){    console.log(abc);}demo4(1,2,3,4,5);//[ 3, 4, 5 ]

11.3 嚴格模式

​ ES2016 做了一點修改,規定只要函數參數使用了默認值、解構賦值、或者擴展運算符,那麼函數內部就不能顯式設定為嚴格模式,否則會報錯。

​ 一般把嚴格模式加在全局。

11.4 name屬性

​ 函數的name屬性,返回該函數的函數名。

function demo(){}
demo.name //demo

11.5 箭頭函數

​ ES6 允許使用「箭頭」(=>)定義函數。

this引用的是定義箭頭函數的上下文

//語法:
  let demo = () => (123||{a:1},[1,2,3])
  //同上
  function demo(){
      return 123||{a:1},[1,2,3];
  }
  let demo = () => {console.log('沒有返回值的箭頭函數')}
  let demo = a => a;
  let demo = (a,b) => { return a+b};

使用注意點:
(1) 函數體內的this對象,就是定義時所在的對象,而不是使用時所在的對象。

箭頭函數內部不自動產生this,而是使用定義箭頭函數時所在位置的外層作用域中的this

​ (2) 不可以當作構造函數

 (3)	不能用作 Generator 函數

​ (4) 不可以使用arguments對象,使用rest參數替代

12.class

12.1 基本使用

	ES6 的class可以看作只是一個語法糖,它的絕大部分功能,ES5 都可以做到,新的class寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的語法而已。
//語法:
class Person{
    //構造方法:默認實例化時會自動調用,做初始化
    constructor(name,age,sex){
        this.name = name;
        this.age =age;
        this.sex = sex;
    }
    say(){
        console.log('我是',this.name);
    }
}
//使用
let obj = new Person('小明',12,'男');
console.log(obj);//Person { name: '小明', age: 12, sex: '男' }
obj.say();//我是 小明

12.2 說明:

  • 在class中定義的方法,是放在構造函數的原型上的

  • 類的內部所有定義的方法,都是不可枚舉的

    conlose.log(Object.keys(Person.prototype));//[]
    console.log(Object.getOwnPropertyNames(Person.prototype));//[ 'constructor', 'say' ]
    
  • 一個類必須有constructor方法,如果沒有顯式定義,一個空的constructor方法會被默認添加

  • 實例化class時,必須有new關鍵字,否則報錯

  • 取值函數(getter)和存值函數(setter)

    get getName(){
            return this.name;
        }
    set setName(value){
        this.name=value;
    }
    
    
    obj.setName='xiaoming';
    console.log(obj.getName);//xiaoming
    obj.say();//我是 xiaoming
    
  • this指向問題

    1. ES6 模塊中,this返回的是當前模塊

    2. 單純作為函數運行,this會指向頂層對象。但是,嚴格模式下,這時this會返回undefined

    3. 如果類中的一個函數不管是通過實例化對象調用還是作為純函數調用,我都想讓函數中的this指向當前類的實例(當前模塊),處理方案有2種

      1. constructor方法中綁定this

         this.say = this.say.bind(this);
        
      2. 使用箭頭函數

        say =()=>{
            
        }
        
  • 靜態方法
    在一個方法前,加上static關鍵字,就表示該方法不會被實例繼承,而是直接通過類來調用,這就稱為「靜態方法」

    class Person{
      static all(){//定義靜態方法
    
      }
    }
    
    //使用:
    Person.all();
    //如果靜態方法包含this關鍵字,這個this指的是類
    
  • 繼承

    • Class 可以通過extends關鍵字實現繼承

      //語法
      class Bird{
          constructor(cb,leg) {
              this.cb=cb;
              this.leg=leg;
          }
          fly(){
              console.log('會飛');
          }
      }
      // 麻雀
      class Maqu extends Bird{
          constructor(cb,leg,name,color){
              super(cb,leg);//調用父類的constructor()
              this.name=name;
              this.color=color;
          }
          tiao(){
              console.log('用'+this.leg+'跳');
          }
      }
      let lily=new Maqu('2隻翅膀','2條腿','lily','白色');
      console.log(lily);//Maqu { cb: '2隻翅膀', leg: '2條腿', name: 'lily', color: '白色' }
      lily.fly();//會飛
      lily.tiao();//用2條腿跳
      
    • super()
      子類必須在constructor方法中調用super方法,否則新建實例時會報錯。這是因為子類自己的this對象,必須先通過父類的構造函數完成塑造,得到與父類同樣的實例屬性和方法,然後再對其進行加工,加上子類自己的實例屬性和方法。如果不調用super方法,子類就得不到this對象。

      //調用父類的constructor()
      super();
      

13.Es6 module

13.1 簡介

​ ES6 模塊功能主要由兩個命令構成:exportimportexport命令用於規定模塊的對外接口,import命令用於輸入其他模塊提供的功能。

//export 導出命令
//  13_moduleA.js
export var num=12;

export function demo(){
    console.log('demo');
}

export let count=10;

export const url='//localhost:3000';

export class Person{
    constructor(name){
        this.name=name;
    }
}

export let jt=()=>{
    console.log('箭頭函數');
}

let num1=1;
let num2=2;
export{
    num1,num2
}

// 重命名導出的模塊 可以使用as關鍵字重命名
export { num as myNum};//將num重命名為  myNum
//import 導入命令
//13_moduleB.js
import {num,demo,count,url,Person,jt,num1,num2} from './13_moduleA.js';
//注意:引入的必須是xx.js中export導出的數據
console.log(num);
demo();
console.log(count);
console.log(url);
let m=new Person('小明');
console.log(m);
jt();

//把xx.js中所有export導出的數據取出來,然後放到obj對象上
import * as obj from './xx.js';

13.2export default 導出命令

  //默認導出,一個js中只能出現一次
  const pic='1.jpg';
  export default pic://導出一個名稱為`default`的模塊
  
  //import 導入 export default模塊語法:
  import A/b/myPic from './xx.js';//隨便命名
  • 使用webpack運行該項目
    安裝:

    npm i -S webpack webpack-cli webpack-dev-server
    npm i -g webpack webpack-cli webpack-dev-server
    

    創建一個配置文件:webpack.config.js
    運行webpack命令,在code文件夾下運行
    webpack ,然後按回車鍵
    在dist文件夾下創建一個index.html,在這個HTML中添加
    在運行一條命令:webpack-dev-server
    在瀏覽器中打開 //localhost:9000/

14.Proxy 代理

14.1 簡介

Proxy 可以理解成,在目標對象之前架設一層「攔截」,外界對該對象的訪問,都必須先通過這層攔截,Proxy 用於修改某些操作的默認行為。

14.2 使用

//語法:
  new Proxy(target,handler);
//返回值----返回一個對象

14.3 Proxy 支持的攔截操作有13個

  • get(target, propKey, receiver):攔截對象屬性的讀取

  • set(target, propKey, value, receiver):攔截對象屬性的設置

    等……

14.4 應用

let obj={
    name:'lilei',
    age:21,
    sex:'男'
}
let proxy=new Proxy(obj,{
    get(target,key,receiver){
        console.log(target,propKey,receiver);//{ name: 'lilei', age: 21, sex: '男' } name { name: 'lilei', age: 21, sex: '男' }
        // console.log('禁止訪問任何屬性');
        // return false;   //1. 
        return '結果:'+Reflect.get(target,key,receiver);//2.
    },
    set(target,propKey,value,receiver){
        console.log(target,propKey,value,receiver);
        //{ name: 'lilei', age: 21, sex: '男' } name 小明 { name: 'lilei', age: 21, sex: '男' }
        return Reflect.set(target,propKey,value,receiver);
    }
});

console.log(proxy.name);//1. false---- 2.結果:lilei
proxy.name='小明';
console.log(proxy.name);//結果:小明
  • 會使用到的一個API,Reflect

15. less

15.1 簡介

lesscss的預處理語言。除了less,還有scss(sass)stylus這些預處理語言。將CSS賦予了動態語言的特性,如 變量, 繼承, 運算, 函數。

css預處理語言編寫的css,瀏覽器是不認識,所以需要首先編譯成純css,需要使用工具。命令行工具 ,gulpwebpack

15.2 安裝

#安裝
npm install xxxxxxxx

#全局安裝,全局安裝後,主要就是給命令行提供命令的
npm i -g less

#項目依賴:就是給當前項目使用的
npm i -S / -D less
#-S 是 --save-dev 的簡寫,作用是開發階段和上線階段都需要使用的模塊,默認值就是-S ,如:npm i less
#-D 是 --save 的簡寫,作用是只在開發階段使用

15.3 使用

  • 創建less文件
    首先創建一個.less結尾的文件
  • 命令行編譯
    lessc xx.less xx.css

15.4 less語法

  1. 變量

    // 定義變量
    @danger:red;
    @baseWidth:20px;
    @baseHeight:10px;
    @warning:yellow;
    @success:green;
    @primary:blue;
    
    #box{
        min-height: @baseHeight*20;
        background: @warning;
        color:@danger;
    }
    
  2. 嵌套

    • 提供了使用嵌套(nesting)代替層疊或與層疊結合使用的能力

      #box{
          min-height: @baseHeight*20;
          background: @warning;
          color:@danger;
          // 嵌套
          .sp1{
              color:@primary;
              font-size:ceil(200/34px);
          }
      }
      
    • &妙用

      .font{
          color:#cccccc;
          font-size:20px;
          // &妙用:代表的上一層選擇器的名字
          &:hover{
              color:darken(@danger,20%);
          }
      }
      
  3. 混合

    • 聲明的集合,使用時 直接鍵入名稱即可

      // margin 集合.margin20{//無參數可省略(    margin:@baseWidth;}// 聲明圓角效果,1. 固定值.radius(){    border-radius: 4px;}// 2. 可變的值.radius2(@w){    border-radius: @w;}// 3. 變量可以有默認值.radius3(@w:5px){    border-radius: @w;}.c1 {    border:1px solid @success;    .margin20;    .radius();}.c2{    border:1px solid @danger;    .margin20;    .radius2(8px);}.c3{    border:2px solid @primary;    .margin20;    .radius3(10px);}
      
      1. 繼承
        可以實現css復用

        #box2{
            &:extend(#box);
            //&:extend(#box .p1 .font);
            //&:extend(#box all);
        }
        //all屬性,繼承整個目標的樣式,包括子級 
        
  4. 導入
    允許在less文件中引入其他的less或css文件

    @import 'path';
    @import 'test.less';
    
  5. 函數
    都是內置的,直接使用就可以

    • 判斷類型
    • 顏色操作
    • 數學函數
  6. 循環方法

// 循環方法
.generate-columns(@n, @i: 1) when (@i =< @n) {
    .column-@{i} {
      width: (@i * 100% / @n);
      height: 10px;
      background:darken(@primary,@i * 5%);
    }
    .generate-columns(@n, (@i + 1));
}
.generate-columns(10);