ES6(阮一峯)學習總結

1.塊級做用域的引入javascript

在ES6以前,js只有全局做用域和函數做用域,ES6中let關鍵字爲其引入了塊級做用域。html

{
var a = 5;
let  b = 6;
}
console.log(a);     //5
console.log(b);     //b is undefined

let聲明的變量只能在其所在的代碼塊內才能訪問,var聲明的變量因爲是全局變量,所以能夠在代碼塊外訪問java

2.暫時性死區node

var聲明的變量能夠在聲明以前使用,至關於默認爲其聲明其值爲undefined了;es6

可是,let聲明的變量一旦用let聲明,那麼在聲明以前,此變量都是不可用的,術語稱爲「暫時性死區」。ajax

console.log(a);                     //undefined
var a=8;
console.log("----------");
console.log(b);                     //控制檯報錯
let b=9;

因此咱們要養成變量先聲明再使用的好習慣。json

3.const命令數組

const用來定義常量,至關於java中的final關鍵字。promise

而且const聲明常量以後就必須當即初始化!瀏覽器

4.解構賦值

let [a,b,c] = [1,2,3];
let{x1,x2} = {x2:5,x1:6};
const [a,b,c,d,e]= "hello";
function  add([i,j]) {}---add([5,6]);

能夠理解爲「模式匹配」。

5.字符串

Unicode表示法

"\u{碼點}"
"\u{41}\u{42}\u{43}"                 //"ABC"
複製代碼
let str = "書劍恩仇錄";
str.codePointAt(0).toString(16);    //返回字符的碼點並由十進制轉到16進制---66f8
String.fromCodePoint(0x66f8);       //返回碼點對應的字符---書
for (let a of str){
   console.log(a);
}                                   //for...of循環遍歷字符串中每一個字符挨個輸出字符
str.at(0);                          //返回指定位置的字符,目前只是提案
str.startsWith('書',0);             //從指定位置日後開始檢查,是否以「書」開始,位置參數可省略,默認爲0
str.endsWith('劍',1);               //從指定位置向前檢查,是否以「劍」結束
str.includes('恩',1);               //同上,再也不囉嗦
str.repeat(2);                      //字符串重複指定次數「書劍恩仇錄書劍恩仇錄」,小數取整,Infinity和負數報錯
str.padStart(8,'ab');               //指定字符從前開始補直到字符串長度符合要求,"aba書劍恩仇錄"
str.padEnd(8,'ab');                 //指定字符從後開始補直到字符串長度符合要求,"書劍恩仇錄aba",若長度小於原長度,返回原字符串,上同
複製代碼

6.模板字符串

模板字符串採用反引號(`)標識,而且模板字符串中的空格、換行將在輸出時有所保留。

複製代碼
// 普通字符串
`In JavaScript '\n' is a line-feed.`

// 多行字符串
`In JavaScript this is
 not legal.`

console.log(`string text line 1
string text line 2`);

// 字符串中嵌入變量
let name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
複製代碼

${主體},其中主體能夠是表達式、運算、對象屬性還能夠是函數,如果字符串將直接輸出該字符串。

7.含參函數的調用

function say(something){
    console.log("she say"+" '"+something+"'" );
}
say`hello`;                             //she say 'hello'

等同於say('hello')。

8.數值拓展

和字符串對象相似的,ES6也爲數值類對象例如Number、Math添加了新的方法以及屬性(常量),在這裏就很少做記錄。

9.函數function

function show(name="jack",sex="boy"){
    console.log(name+" is a "+sex+"!");
}
show();                                  //jack is a boy!
show('judy');                            //judy is a boy!
show('judy','girl');                     //judy is a girl!

爲函數的參數添加默認值,執行函數時若是不傳該參數,那麼就用默認值代替。

箭頭函數:

var 變量名/函數名 = (參數,參數)=>{代碼塊}

複製代碼
var f = v => v;
//等同於
var f = function(v) {
  return v;
};

var f = () => 5;
// 等同於
var f = function () { return 5 };

var sum = (num1, num2) => num1 + num2;
// 等同於
var sum = function(num1, num2) {
  return num1 + num2;
};
複製代碼

注意:若是return的是一個對象{id:id,age:age},那麼箭頭右邊要用括號包起來().

10.數組的擴展

擴展運算符爲三個點(...),將一個數組轉化爲參數序列,一般與函數一塊兒使用,show(...['judy','girl'])。

數組合並:[...arr1,...arr2,...arr3]

字符串轉字符數組:[..."hello"]--------------["h","e","l","l","o"]

將實現Iterator接口的對象轉化爲真正的數組:[...nodelist],這裏的nodelist是一個相似於數組的nodelist對象

Generator 函數:該函數執行後返回一個遍歷器對象,拓展運算符也可將其轉化爲數組。

複製代碼
let a =function*(){
    yield 3;
    yield 4;
    yield 5;
    return 6;
};
console.log([...a()]);              //[3,4,5]
複製代碼

11.數組的方法

Array.from(對象,對新數組各項的改動規則)

這裏的對象只適合①類數組對象②實現Iterator接口的對象;後面的規則可選

e.g:

Array.from([1, 2, 3], (x) => x * x)          //這裏將數組每項按必定規則改變生成新數組[1,4,9]

Array.of(數據1,數據2,數據3)

將一組數據轉化爲數組

e.g:

Array.of(1,2,3,4,5)                               //[1,2,3,4,5]

copyWithin(被覆蓋起始位置,選取的數據起始位置,選取額數據結束位置)

截取數組的一段數據,並覆蓋到指定位置

e.g:

[1,2,3,4,5].copyWithin(0,2,4)               //被截取數據位置爲[2,4)---[3,4],替換起始位置是0,因此結果是[3,4,3,4,5]

find(規則)、findIndex(規則)

這裏的規則是一個回調函數,找到了就返回這個數組項/索引,找不到返回undefined/-1

e.g:

[9,8,7,6,5,4,3].find(n=>n<5)                //返回4

還能夠添加第二個參數,以下

複製代碼
function f(v){
    return v > this.age;
}
let  c =function(v){
    return v > this.age;
}
let person = {name: 'John', age: 20};
let a  =[10, 12, 26, 15].find(c, person);            //c、f均可以  
console.log(a);                                      //26
複製代碼

fill(被填充數據,起始位置,結束位置)

若是起始位置、結束位置不寫,那麼就默認所有填充

e.g:

[2,2,2,2,2,2].fill(8,2,4)                                //將8覆蓋原[2,4)位置上的數據,[2,2,8,8,2,2]

注意,若是給每項賦值的是一個對象,那麼實際上只是一個指針,若改變一個位置的對象內容,那麼全部項

的對象內容都會改變。

let b = {name:'jack'};
let a =[2,2,2,2,2,2].fill(b,1,4) ;
console.log(a);               //[ 2, { name: 'jack' }, { name: 'jack' }, { name: 'jack' }, 2, 2 ]
a[1].name = "echo";
console.log(a);               //[ 2, { name: 'echo' }, { name: 'echo' }, { name: 'echo' }, 2, 2 ]

for...of遍歷數組的鍵、值、以及各項鍵值對信息

複製代碼
for (let index of ['a', 'b'].keys()) {
    console.log(index);
}
// 0
// 1

for (let elem of ['a', 'b'].values()) {
    console.log(elem);
}
// 'a'
// 'b'

for (let [index, elem] of ['a', 'b'].entries()) {
    console.log(index, elem);
}
// 0 "a"
// 1 "b"
複製代碼

備註:有的瀏覽器沒有實現數組的values()方法,好比:Chrome!

12:對象的拓展

對象裏面能夠直接寫入變量和函數

複製代碼
//before:
var person = {
    name:'eco',
    age:18,
    say:function(something){
        console.log("hello "+something);
    }
};
person.say('world');

//now:
var firstname='jack';
var man = {
    firstname,
    say(something){
        console.log(this.firstname);
        console.log("hello "+something);
    }
};
man.say('world');
複製代碼

屬性名/方法名:能夠用中括號裏面加上表達式的方式

e.g:

var a = 'age';

person.age=person['age']=person[a]

方法的name屬性返回方法名

person.say.name                                    //"say"

Object.is(值1,值2)用於比較兩個值是否相等,返回布爾值

Object.assign(targetobject,sourceobject1,sourceobject2)

用於對象的合併,將源對象合併到目標對象,如有相同屬性源對象屬性覆蓋目標對象屬性

若是源對象是其餘數據類型,只有字符串會以字符數組形式拷到目標對象,其餘類型不會有效果。

const v1 = 'abc';
const v2 = true;
const v3 = 10;

const obj = Object.assign({}, v1, v2, v3);
console.log(obj);           // { "0": "a", "1": "b", "2": "c" }

對象的屬性描述:Object.getOwnPropertyDescriptors(obj)

對象的繼承相關:

Object,setPrototypeOf(obj,proto)                    //爲obj對象設置一個原型對象,那麼obj繼承了proto對象的全部屬性

Object.getPrototypeOf(obj)                             //不難看出,這是讀取一個對象的原型對象

super                                                               //指向當前對象的原型對象,至關於java中的超類

13.Symbol函數

爲了防止不一樣人員書寫代碼形成變量名/方法名的衝突

let a = Symbol();
let b = Symbol();
//函數能夠添加帶有描述性語言的字符串參數
a === b ;          
//false

14.Set和Map數據結構

Set:成員不重複的類數組結構

Set屬性:size---返回成員總數

Set操做方法:add(value)---返回Set、delete(value)---返回布爾、has(value)---返回布爾、clear()---無返回值

Set遍歷方法:keys()---返回鍵(索引)的遍歷器、values()---返回值的遍歷器、

                       entries---返回鍵值對的遍歷器、forEach(callback())---遍歷每一個成員,並經過回調函數基於數據作點什麼

WeakSet:相似於Set,只是它的成員只能是對象,沒有size,不能遍歷

Map:廣義上的鍵值對集合,鍵的範圍不侷限於字符串,對象也能夠看成鍵

Map操做方法:set(key,value)---設置成員、get(key)---讀取指定鍵的值,若無返回undefined

複製代碼
const set = new Set([1, 2, 3, 4, 4]);
//[...set]---[1,2,3,4]

const map = new Map([
    ['name', '張三'],
    ['title', 'Author']
]);
複製代碼

 15.Proxy代理

複製代碼
var handler = {
    get: function(target, name) {
        if (name === 'prototype') {
            return Object.prototype;
        }
        return 'Hello, ' + name;
    },

    apply: function(target, thisBinding, args) {
        return args[0];
    },

    construct: function(target, args) {
        return {value: args[1]};
    }
};

var fproxy = new Proxy(function(x, y) {
    return x + y;
}, handler);

fproxy(1, 2)                                      // 1
new fproxy(1, 2)                                  // {value: 2}
fproxy.prototype === Object.prototype             // true
fproxy.foo === "Hello, foo"                       // true
複製代碼

咱們能夠看出,上面聲明瞭一個變量/函數fproxy,而且爲其添加了一個攔截器對象handler,

那麼對fproxy進行一些操做行爲的時候,會優先被這個攔截器捕獲,進行特定處理後輸出結果

var fproxy = new Proxy(target,handler);            //一個Proxy實例

construct:構造一個新的fproxy時會觸發攔截器的該方法,new fproxy(1,2)===>return {value : args[1]}===>{value : 2}

apply:函數執行時會觸發攔截器的該方法,fproxy(1,2)===>return args[0]===>1

get:讀取屬性值的時候會觸發攔截器的該方法,fproxy.foo===>foo對應該方法的參數name,return 'Hello, '+name;===>"Hello, foo"

set:設置屬性值的時候會觸發攔截器的該方法。

備註:

let obj = Object.create(fproxy);

這裏爲obj設置了原型fproxy,那麼obj繼承了fproxy的全部屬性,obj.foo===>fproxy.foo===>"Hello, foo"

Proxy支持的攔截操做除了上面的4中以外還有9中,有興趣的請點擊 Proxy

16.Reflect反射

相似於java的反射,在跳過編譯、不加載類的前提下,動態地調用類中的方法。

和Proxy相對應的,Reflect也有13個靜態方法,詳情請點擊 Reflect

Reflect.get(target,name,receiver)------------讀取target對象(必須是對象)的name屬性值,若無返回undefined,

                                                                   若name屬性有get聲明,那麼name函數中的this指向receiver對象。

Reflect.set(target,name,value,receiver)----設置target對象(必須是對象)的name屬性值爲value,

                                                                   若name屬性有set聲明,那麼name函數中的this指向receiver對象。

注意:當Proxy和Reflect同時使用時,爲一個Proxy實例賦值時,觸發set攔截,若set攔截方法體內又有

           Reflect.set(target,name,value,receiver),那麼這又會觸發攔截器的defineProperty攔截,前提是反射操做

           傳入了receiver參數!!!

Reflect.has(obj,name)---------------------------返回布爾值,表示obj對象中有沒有name屬性。

17.Promise---異步

先來看ajax的異步:

複製代碼
$(function(){
    $('#send').click(function(){
         $.ajax({
             type: "GET",
             url: "test.json",
             data: {username:$("#username").val(), content:$("#content").val()},
             dataType: "json",
             success: function(data){
                         $('#resText').empty();   //清空resText裏面的全部內容
                         var html = ''; 
                         $.each(data, function(commentIndex, comment){
                               html += '<div class="comment"><h6>' + comment['username']
                                         + ':</h6><p class="para"' + comment['content']
                                         + '</p></div>';
                         });
                         $('#resText').html(html);
                      }
         });
    });
});
複製代碼

上面的例子實現了一個相似於表單提交的功能。

Promise的異步:

複製代碼
let promise = new Promise(function(resolve, reject) {
  console.log('Promise');                        //實例化後當即執行
  resolve();                                     //任務(成功)完成
});

promise.then(function() {
  console.log('resolved.');                      //任務結束執行
});

console.log('Hi!');                              //在實例化promise的同時,執行
複製代碼

顯示順序:"Promise"---"Hi"---"resolved"

能夠看出,在promise執行的整個過程當中(實例化到結束),並無阻塞其餘外部語句的執行,換句話說,其餘語句

不用等到輸出"resolved"以後再執行。

複製代碼
function loadImageAsync(url) {
  return new Promise(function(resolve, reject) {
    const image = new Image();

    image.onload = function() {
      resolve(image);                        //promise對象狀態變爲resolved
    };

    image.onerror = function() {
      reject(new Error('Could not load image at ' + url));
    };                                       //promise對象狀態變爲rejected並拋出錯誤

    image.src = url;
  });
}
複製代碼

注意:上面狀態改變時傳入函數的參數(image、new Error),會傳到以後then函數,做爲then函數的參數的參數!!!

loadImageAsync(url).then(  function(success){console.log(success);}    ,function(error){console.log(error);});

這裏的success接收來自resolved狀態的參數image,error接收來自rejected狀態的參數new Error。

事實上then後面還能夠加上一個catch函數用來捕捉rejected狀態產生的錯誤,這樣就能夠省略掉then函數裏面的第二個參數

promise.then(success()).catch(error()).finally(function(){});

看上去是否是相似於java的try...catch...finally呢?

其餘方法請戳===>Promise

18.Iterator接口

具有Iterator接口的原生數據結構:

Array---Map---Set---String---TypedArray---NodeList對象---函數的arguments對象。

實用場景:

解構賦值:let [x,y] = new Set([1,2,3])                             //x=1;y=2

擴展運算符:[...iterable]                                                 //將實現Iterator接口的對象轉化爲數組

yield*:yield*[2,3,4]---yield 2;yield 3;yield 4;                   //generator函數內部

....

實現了Iterator接口的數據類型,都會有一個屬性[Symbol.iterator],固定寫法,它是一個函數,返回一個遍歷器對象

複製代碼
e.g:
let arr = ['a', 'b', 'c'];
let iter = arr[Symbol.iterator]();                 //返回一個遍歷器
iter.next()                                        // { value: 'a', done: false }
iter.next()                                        // { value: 'b', done: false }
iter.next()                                        // { value: 'c', done: false }
iter.next()                                        // { value: undefined, done: true }
複製代碼

注意:

for...in循環:只能獲取對象的鍵名

for...of循環:能夠得到鍵值,只返回具備數字索引的屬性(鍵或值)

複製代碼
var arr = ['a', 'b', 'c', 'd'];

for (let a in arr) {
  console.log(a);                  // 0 1 2 3
}

for (let a of arr) {
  console.log(a);                  // a b c d
}
複製代碼

19.Generator函數補充

複製代碼
let a =function*(){
    yield 3;
    yield 4;
    yield 5;
    return 6;
};
console.log([...a()]);              //[3,4,5]
複製代碼

只有執行a().next(),函數內部的語句纔會執行一次,每調用一次next()函數執行一次內部函數。

e.g:

複製代碼
function* dataConsumer() {
  console.log('Started');
  console.log(`1. ${yield}`);
  console.log(`2. ${yield}`);
  return 'result';
}

let genObj = dataConsumer();
genObj.next();            // Started;執行了第一條語句
genObj.next('a')          // 1. a;執行了第二條語句
genObj.next('b')          // 2. b;執行了第三條語句
複製代碼

next()函數有一個可選參數,用來表示上一次yield表達式值。

e.g:

複製代碼
function* foo(x) {
  var y = 2 * (yield (x + 1));
  var z = yield (y / 3);
  return (x + y + z);
}

var b = foo(5);
b.next()                   // { value:6, done:false }
b.next(12)                 // { value:8, done:false }
b.next(13)                 // { value:42, done:true }
複製代碼

解析:

第一次next(),x=5,那麼yield(x+1)=6---{value:6,done:false}

第二次next(12),令yield(x+1)=12,那麼y=24,輸出yield(y/3)=8---{value:8,done:false}

第三次next(13),令yield(y/3)=13,前面yield(x+1)=12,那麼最終z=13,y=24,x=5,return (x+y+z)=42---{value:42,done:true}

throw:

兩種throw:遍歷器對象的throw(),全局命令throw

iter.throw(error),這個錯誤會被遍歷器函數內部的catch捕獲,

iter.throw(error),遍歷器對象再次拋出錯誤,因爲內部的catch已經執行了,那麼此次的error會被外部的catch捕獲

throw new Error(error),這是個全局命令,會被全局(外部)做用域的catch捕獲,遍歷器對象內部的catch是不能捕獲的

遍歷器拋出的錯誤優先被遍歷器內部捕獲,內部沒有catch纔會被外部catch捕獲

①遍歷器捕捉到錯誤以後,除了執行catch內部的命令以外,還會自動執行一次next()方法。

②Generator 執行過程當中拋出錯誤,且沒有被內部捕獲,就不會再執行下去了。

若是此後還調用next方法,將返回一個value屬性等於undefined、done屬性等於true的對象。

③遍歷器的return(參數)方法會終結函數,並返回一個對象{value:參數,done:true},參數爲空,value爲undefined。

若是有finally,那麼這個return會在finally結束後執行。

④要在gen函數內部調用別的gen函數,要使用yield* gen()語句,若是沒有這個*號,那麼next().value返回的是一個遍歷器對象

20.async函數

async就表示asynchronous(異步的),async函數會返回一個Promise對象,天然可以調用其方法:

promise.then(success()).catch(error()).finally(function(){});

複製代碼
async function getStockPriceByName(name) {
    const symbol = await getStockSymbol(name);
    const stockPrice = await getStockPrice(symbol);
    return stockPrice;             //stockPrice是一個promise對象
}

getStockPriceByName('goog').then(function (result) {
    console.log(result);
});
複製代碼

能夠看出,它和通常函數沒多大區別,只是多了一個async標識。

注意:上面所說到的返回一個對象,這個對象自己沒什麼特別,只是他能夠做爲promise對象,在調用then方法的時候做爲參數傳

到函數裏面。並且由於這個對象會被當作promisi對象,return關鍵字能夠替換成await。

21.class

複製代碼
class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }

    toString() {
        return '(' + this.x + ', ' + this.y + ')';
    }
}
var a = new Point(1,2);
console.log(a.x);                      //1
console.log(a.toString());             //(1,2)
a.hasOwnProperty('x')                  // true
a.hasOwnProperty('y')                  // true
a.hasOwnProperty('toString')           // false
a.__proto__.hasOwnProperty('toString') // true
複製代碼

a是沒有定義toString()方法的,因此從它的原型Point上調用此方法。

繼承:extends關鍵字

複製代碼
class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y);                                // 調用父類的constructor(x, y)
    this.color = color;
  }

  toString() {
    return this.color + ' ' + super.toString(); // 調用父類的toString()
  }
}
複製代碼

繼承了父類的全部屬性,也能夠添加或者修改屬性

22.模塊化

複製代碼
//lib.js
var counter = 3;
function incCounter() {
  counter++;
}
module.exports = {
  counter: counter,
  incCounter: incCounter,
};
複製代碼

這是一個js模塊,對外暴露兩個屬性counter(變量)、incCounter(函數),而後再去加載這個模塊

// main.js
var mod = require('./lib');

console.log(mod.counter);  // 3
mod.incCounter();
console.log(mod.counter);  // 3

這樣就能夠去調用該模塊對外暴露的屬性了,

 

(我不怕千萬人阻擋,只怕本身投降!)
相關文章
相關標籤/搜索