中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

es6學習筆記

發布時間:2020-07-30 18:52:19 來源:網絡 閱讀:454 作者:xxxpjgl 欄目:web開發

★★代碼都是從上到下依次執行,寫在前面的先執行,別跳看!!一步一步的來!!
一、promise對象的使用
Promise處理的是一個異步問題
通常情況:回調函數是異步編程解決方案的一種
只要是回調函數,都可以改寫成promise寫法!

function send( url,callback ){
    //var xhr =...
    //...
    callback();  //回調函數這么使用
}

send( 'url1',()=>{  //參數是一個回調函數
    //do something
} )

Promise是一個構造函數,使用的時候需要new一下,Promise需要接收一個參數,這個參數是一個函數,并且該函數需要傳入2個參數resolve、reject,分別表示異步操作執行成功后的回調函數和異步操作執行失敗后的回調函數。

1.1、我們用Promise的時候一般是包在一個函數中,在需要的時候去運行這個函數,因為new promise的時候,傳入其中的函數會自動執行,所以我們需要控制其中的函數在需要的時候才去執行

1.2、對于Promise的then()方法,then總是會返回一個Promise實例,因此你可以一直調用then,then接收一個函數,函數接收2個參數resolve、reject

var p = new Promise( ()=>{  
     console.log('執行了');  //定義Promise對象的時候,一定要傳入一個函數,否則報錯,而且這個函數在創建Promise對象的時候聚立即執行了。 此時Promise對象的狀態是pending
} )
//傳入參數resolve,reject,執行 resolve();就把Promise變成成功的狀態了;執行 reject();就把Promise變成失敗的狀態了
var p = new Promise( (resolve,reject)=>{  
    //這里面可以執行別的自定義方法,不一定只能是resolve或者reject,在自定義方法里面,設置什么時候執行resolve,什么時候執行reject,下面使用catch捕捉reject
    console.log(1);  //執行到這里,下面馬上把promise變為成功狀態
     resolve();  //把Promise變成成功的狀態
} )
var p = new Promise( (resolve,reject)=>{   //內部有三種狀態,pending、resolve、reject
    return resolve("成功");  //進入成功執行的代碼  一般會加個return,阻止后續代碼的執行
    reject(); //進入執行失敗的代碼   resolve與reject二者只會執行前一個,后者不會執行,但是后續的代碼還會繼續執行;resolve(data)有參數,then用data接收,reject(err)也有參數,catch用err接收
    console.log();  //會繼續執行到這里
} )
p.then( (data)=>{  //這里的data接收上面resolve傳入的"成功"字符串
    console.log("then:"+data);
} )

1.3、then方法是一個實例方法,建立在返回p實例的基礎上

then( ()=>{  //then接收一個函數,函數接收2個參數,前者是上面進入成功狀態執行,后者是上面進入失敗狀態執行
    console.log('成功')    //上面的resolve()時進入這里
},()=>{  //上面的reject()時進入這里
    console.log('失敗')
} )  

tips、但是一般不使用上面的寫法

p.then( (data)=>{  //then默認返回成功狀態
    console.log(data); //成功
} )  //成功狀態時進入
p.catch( ()=>{
    console.log("失敗");
} )  //失敗狀態時進入

var p = new Promise( (resolve,reject)=>{
    resolve("成功");
} )

var p2 = p.then( ()=>{} );  //執行完返回的promise是成功的狀態,p2.then走成功resolve()方法
//這里沒有返回值,就相當于return undefined,返回undefined

var p2 = p.then( ()=>{
    return "非promise對象"  //執行完返回的promise也是成功的狀態
} )

后續鏈式調用then方法,返回的是一個Promise對象,這個返回的Promise對象的狀態是成功還是失敗,取決于then方法內部的代碼,如果內部代碼返回的是非Promise對象,無論是有值還是undefined,都是resolve(),否則,如果內部返回的是Promise對象,那么如果該返回的Promise對象是reject,那么then返回的是reject,否則就是resolve

1.4、catch方法
catch相當于then的第二個參數

var p = new Promise( (res,rej)=>{
    res('成功');
} )
p.then( ()=>{
    console.log( 1 )
} ).then( ()=>{
    console.log( 2 )
} ).catch( (err)=>{  //捕捉失敗
    console.log(err)
} ).finally( ()=>{  //匿名函數里面沒有參數了,不管執行了成功還是失敗,這里都會執行到
    console.log('執行完畢');
} )
console.log('這兒的代碼仍然能執行');
//執行了catch方法,捕捉錯誤,不會影響后續代碼的執行

=====等價于======

var p = new Promise( (res,rej)=>{
    res('成功');
} )

let res = p.then( ()=>{  //執行完then,永遠都返回promise對象,成功還是失敗取決于返回的類型,成功繼續走then,失敗走catch
    console.log( 1 )
} ).then( ()=>{
    console.log( 2 )
} )

res.catch( (err)=>{  //捕捉失敗
    console.log(err)
} ).finally( ()=>{  //匿名函數里面沒有參數了,不管執行了成功還是失敗,這里都會執行到
    console.log('執行完畢');
} )
console.log('這兒的代碼仍然能執行');
//執行了catch方法,捕捉錯誤,不會影響后續代碼的執行

p.then(data)里面的data接收的是上面resolve()里面傳入的值

1.5、Promise靜態方法

一個成功
p.then( ()=>{ console.log(1)} )
.then( ()=>{ return new Promise( (res,rej)=>{return res(400)} ) } )
.then( ()=>{ return Promise.resolve(400) } )  //兩種寫法一樣
.then( (data)=>{console.log(data)} )   //400

一個失敗
p.then( ()=>{ console.log(1)} )
.then( ()=>{ return new Promise( (res,rej)=>{return rej(400)} ) } )
.then( ()=>{ return Promise.reject('失敗!') } )  //兩種寫法一樣
.catch( (err)=>{console.log(err)} )   //失敗!

//all方法:合并所有的promise對象,返回所有promise全部執行完之后的結果
let p1 = new Promise(()=>{ setTimeout(()=>{ res('a') },500) })
let p2 = new Promise(()=>{ setTimeout(()=>{ res('b') },500) })
let p3 = new Promise(()=>{ setTimeout(()=>{ res('c') },500) })
var p = Promise.all( [p1,p2,p3] );
p.then( (data)=>{ console.log(data) } )  //獲取所有的promise完成之后的數據,保存為一個數組 ['a','b','c']

//race方法:返回所有promise中最先執行完的那個的結果
var p = Promise.race( [p1,p2,p3] );
p.then( (data)=>{ console.log(data) } )  //獲取所有的promise中最先完成的那個數據

案例:


let p = new Promise((resolve,reject)=>{
    resolve('成功');
})
p.then((data)=>{
    console.log(data);  //成功
})
console.log(p);  //Promise?{<resolved>: "成功"}

new Promise((resolve,reject)=>{
    resolve('成功啊啊啊');
})
.then((data)=>{
    console.log(data);  //成功啊啊啊
})

let box = document.getElementById("box");
function movePromise(obj,attr,target,duration){

    return new Promise((res,rej)=>{
        let b = parseInt(getComputedStyle(obj)[attr]); //obj沒有引號,attr是字符串類型
        let c = target - b ;
        let d = duration;
        let temp = new Date().getTime();
        let timer = setInterval(function(){
            let t = new Date().getTime() - temp;
            if(t >= d){
                clearInterval(timer);
                t = d;
            }
            let v = c/d*t + b;
            obj.style[attr] = v + 'px';
            if(t === d){
                res();
            }
        },20)
    })
}
movePromise(box,"width",200,500)
.then( (res,rej)=>{
    movePromise(box,"height",300,500)
} )
//這里面不是直接promise后接著執行then,而是promise外面的函數來執行then方法,所以里面的peomise需要加上return了,讓外面的函數執行完畢之后返回一個promise對象
雖然promise會默認返回一個promise,但是需要return出來,才能讓外面的函數接著執行then方法

二、定義變量:var、let聲明變量,const聲明常量

1、var聲明的變量支持預解析(變量提升),let不支持

var a = 1;
console.log(a);  //1

var c;
console.log(c);  //undefined,先聲明未賦值,值為undefined,沒有保錯

console.log(d);  //undefined,預解析(變量提升),值為undefined,沒有保錯
var d;(var d = 2;)都是輸出undefined

let e;
console.log(e);  //undefined,先聲明未賦值,值為undefined,沒有保錯

console.log(f);  //Uncaught ReferenceError: f is not defined,報錯
let f;

console.log(g);  //Uncaught ReferenceError: g is not defined,報錯
let g = 1;

let b = 2;
console.log(b);  //2,正確輸出

2、var可以重復聲明,后面的值會覆蓋前面的,let不能重復聲明,會報錯

var x = 1;
var x = 2;  //2
let m = 1;
let m = 100;  //Uncaught SyntaxError: Identifier 'm' has already been declared,報錯

3、let支持塊級作用域,塊級作用域內的變量外部訪問不到,但是var可以,(內部二者都可以訪問到)

{
    var a = 1;
    console.log(a);  //1
}
console.log(a);  //1

{
    let a = 1;  
    console.log(a);  //1
}
console.log(a);  //Uncaught ReferenceError: a is not defined

4、const聲明常量
const聲明一個常量之后,不可修改,
和let一樣,不可重復聲明,不支持預解析,支持塊級作用域
let和var可以只聲明,不賦值;const不可以,聲明的同時必須進行賦值

三、函數聲明
1、JS中常見的兩種函數聲明(statement)方式有這兩種:

// 函數表達式(function expression) 
h();  //報錯
var h = function() {
      // h
}
h();  //正確

m();  //正確
// 函數聲明(function declaration) 
function m() {
      //m
}
m();  //正確
  • 先說兩者的顯著區別:
  • 第一種聲明方式也就是var聲明方式, 函數只有在var語句聲明之后才能被調用
  • 第二種生命方式也就是function聲明方式, 函數可以在function聲明之前被調用
  • 這是因為,
  • 對第一種情況,函數表達式是在函數運行階段才賦值給變量h
  • 對第二種情況,函數表達式是在代碼運行階段之前,也就是代碼預解析階段賦值給標識符m

2、總結

  • 函數表達式: 即上面第一種方式, 這種方法使用function操作符創建函數, 表達式可以存儲在變量或者對象屬性里. 函數表達式往往被稱為匿名函數, 因為它沒有名字. 證明這一點你可以 console.log(h.name); 可以看到打印為空 ""
  • 函數聲明: 即上面第二種方式, 會聲明一個具名函數, 且函數能在其所在作用域的任意位置被調用, 其創建的函數為具名函數, 證明這一點你可以 console.log(m.name); 可以看到打印為 "m". 可在后面的代碼中將此函數通過函數名賦值給變量或者對象屬性

四、解構賦值
1、數組的解構賦值
和對象差不多,嚴格按照數組下標來取值

let arr = [1,2,3];
let [a,b,c] = arr
console.log(a,b,c);  // 1 2 3
let [a,,c] = arr;
console.log(a,c);  // 1  3
let [a,,c,d=4] = arr;  //支持賦默認值
console.log(a,c,d);  //1 3 4
let [a,...rest] = arr;
console.log(a,rest);  //1 (2)?[2, 3]

2、字符串的解構賦值
3、對象的解構賦值

let obj = {
    name:'leo',
    age:20,
    b:1,
    move:function(){
        console.log(1)
    }
}
let {name,age} = obj;//聲明的同時解構賦值,{}里的變量名必須和obj里面的變量名一致
console.log(name,age);  //leo 20
★對象的結構賦值,可以只取對象中的某一個屬性,不是必須一次性全部取出來
let {name} = obj;
console.log(name);  //20

//可以解構賦值取別名
let { name : str } = obj;
console.log(str)  //leo
console.log(name)  //無值
//可以賦默認值,obj里面沒有該屬性則取賦的默認值,有屬性則取obj里面的值
let { name = 'xx' } = obj;
console.log(name)  //leo
let { c = 'xx' } = obj;
console.log(c)  //xx
//...取剩余的元素,歸到一個數組里
let {b,...r} = obj;
console.log(b,r);  //1 {name: "leo", age: 20, move: ?}

五、擴展運算符...與rest運算符...
1、擴展運算符
1.1、用三個點號表示,功能是把數組或類數組對象展開成一系列用逗號隔開的值

var foo = function(a, b, c) {
    console.log(a);
    console.log(b);
    console.log(c);
}
var arr = [1, 2, 3];
//傳統寫法
foo(arr[0], arr[1], arr[2]);
//使用擴展運算符
foo(...arr);  //這里面的arr就可以看作,獲取到了arr里面所有的值了
//1
//2
//3

1.2、特殊應用場景:

//數組深拷貝
var arr2 = arr;
var arr3 = [...arr];
console.log(arr===arr2); //true, 說明arr和arr2指向同一個數組
console.log(arr===arr3); //false, 說明arr3和arr指向不同數組
//把一個數組插入另一個數組字面量
var arr4 = [...arr, 4, 5, 6];
console.log(arr4);//[1, 2, 3, 4, 5, 6]
//字符串轉數組
var str = 'love';
var arr5 = [...str];
console.log(arr5);//[ 'l', 'o', 'v', 'e' ]

2、rest運算符
2.1、rest運算符也是三個點號,不過其功能與擴展運算符恰好相反,把逗號隔開的值序列組合成一個數組

//主要用于不定參數,所以ES6開始可以不再使用arguments對象
var bar = function(...args) {
    for (let el of args) {
        console.log(el);
    }
}

bar(1, 2, 3, 4);
//1
//2
//3
//4
bar = function(a, ...args) {
    console.log(a);
    console.log(args);
}
bar(1, 2, 3, 4);
//1
//[ 2, 3, 4 ]

2.2、rest運算符配合解構使用:

var [a, ...rest] = [1, 2, 3, 4];
console.log(a);//1
console.log(rest);//[2, 3, 4]

小結:

  • 等號表達式是典型的賦值形式,函數傳參和for循環的變量都是特殊形式的賦值。解構的原理是賦值的兩邊具有相同的結構,就可以正確取出數組或對象里面的元素或屬性值,省略了使用下標逐個賦值的麻煩。

  • 對于三個點號,三點放在形參或者等號左邊為rest運算符; 放在實參或者等號右邊為擴展運算符,或者說,放在被賦值一方為rest運算符,放在賦值一方為擴展運算符。

一點經驗:

  • 在等號賦值或for循環中,如果需要從數組或對象中取值,盡量使用解構。
  • 在自己定義函數的時候,如果調用者傳來的是數組或對象,形參盡量使用解構方式,優先使用對象解構,其次是數組解構。代碼可讀性會很好。
  • 在調用第三方函數的時候,如果該函數接受多個參數,并且你要傳入的實參為數組,則使用擴展運算符。可以避免使用下標形式傳入參數。也可以避免很多人習慣的使用apply方法傳入數組。
  • rest運算符使用場景應該稍少一些,主要是處理不定數量參數,可以避免arguments對象的使用。
    六、map、forEach、filter、some的區別
    map和forEach的遍歷方法不同,在forEach中return語句是沒有任何效果的,而map則可以改變當前循環的值,返回一個新的被改變過值之后的數組(map需return),一般用來處理需要修改某一個數組的值。
    let arr1 = [1,2,3];
    let arr2 = arr1.map((value,key,arr) => {
    console.log(value)    // 1,2,3
    console.log(key)      // 0,1,2
    console.log(arr)      //[1,2,3] [1,2,3] [1,2,3]
    return value * value;
    })
    console.log(arr1); // [ 1, 2, 3 ]
    console.log(arr2); // [ 1, 4, 9 ]  //返回一個新的數組,如果在forEach里面使用return,則沒有這個效果

    filter函數可以看成是一個過濾函數,返回符合條件的元素的數組
    filter需要在循環的時候判斷一下是true還是false,是true才會返回這個元素;

    let arr1 = [1,2,3];
    let arr2 = arr1.filter((value,key,arr) => {
    console.log(value)    // 1,2,3
    console.log(key)      // 0,1,2
    console.log(arr)      // [1,2,3]
    return value >= 3 ? false : true;     
    })
    console.log(arr1); // [ 1, 2, 3 ]
    console.log(arr2); // [ 1, 2 ]

    some()方法
    Array.some(function( item ){})

  • 用于檢測數組中的元素是否滿足指定條件(函數提供),會依次執行數組的每個元素
  • 如果有一個元素滿足條件,則表達式返回true , 剩余的元素不會再執行檢測
  • 如果沒有滿足條件的元素,則返回false
  • 如果return返回值有一項為true,那么結果就是true

七、Object.assign
Object.assign是ES6新添加的接口,主要的用途是用來合并多個JavaScript的對象。
Object.assign()接口可以接收多個參數,第一個參數是目標對象,后面的都是源對象,assign方法將多個原對象的屬性和方法都合并到了目標對象上面,如果在這個過程中出現同名的屬性(方法),后合并的屬性(方法)會覆蓋之前的同名屬性(方法)。
assign的基本用法如下:

var target  = {a : 1}; //目標對象
var source1 = {b : 2}; //源對象1
var source2 = {c : 3}; //源對象2
var source3 = {c : 4}; //源對象3,和source2中的對象有同名屬性c
var obj = Object.assign(target,source1,source2,source3);
//結果如下:
//{a:1,b:2,c:4}
  • Object.assign拷貝的屬性是有限制的,只會拷貝對象本身的屬性(不會拷貝繼承屬性),也不會拷貝不可枚舉的屬性。但是屬性名為Symbol值的屬性,是可以被Object.assign拷貝的。
  • 如果assign只接收到了一個對象作為參數的話,就是說沒有源對象要合并到目標對象上,那會原樣把目標對象返回。

1、Object.assign進行的拷貝是淺拷貝。也就是說,如果拷貝過來的屬性的值是對象等復合屬性,那么只能拷貝過來一個引用。

const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);

obj1.a.b = 2;
obj2.a.b // 2

由于是淺拷貝,拷貝的是引用,obj1的值改變,obj2的屬性值也會隨之改變
2、Object.assign進行合并的時候,一旦碰到同名屬性,就會出現覆蓋現象。所以使用時務必小心。
3、Object.assign是針對Object開發的API,一旦在源對象的參數未知接收到了其他類型的參數,會嘗試類型轉換。如果是數組類型的話,類型轉換的結果是將每個數組成員的值作為屬性鍵值,將數組成員在數組中的位置作為屬性鍵名。多個數組組成參數一同傳入的話還會造成覆蓋。具體例子如下:

Object.assign([1, 2, 3], [4, 5])
// [4, 5, 3]

上面代碼中,assign把數組視為屬性名為 0、1、2 的對象,因此源數組的 0 號屬性4覆蓋了目標數組的 0 號屬性1。
4、Object.assign只能將屬性值進行復制,如果屬性值是一個get(取值函數)的話,那么會先求值,然后再復制。

// 源對象
const source = {
   //屬性是取值函數
   get foo(){return 1}
};
//目標對象
const target = {};
Object.assign(target,source);
//{foo ; 1}  此時foo的值是get函數的求值結果
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

大理市| 定南县| 盐亭县| 甘肃省| 阿鲁科尔沁旗| 江达县| 南郑县| 砚山县| 西乌珠穆沁旗| 松原市| 仙桃市| 阿拉善左旗| 游戏| 淄博市| 那坡县| 会东县| 车险| 灵石县| 怀仁县| 米泉市| 虎林市| 芜湖市| 江源县| 河北省| 琼中| 上蔡县| 天台县| 清新县| 瑞昌市| 农安县| 萨嘎县| 柳河县| 施秉县| 奉贤区| 宕昌县| 武汉市| 麦盖提县| 河北省| 抚州市| 得荣县| 澳门|