成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

從0到1使用VUE-CLI3開發(fā)實戰(zhàn)(三): ES6/ES7知識儲備

crossoverJie / 403人閱讀

摘要:它們都用于聲明變量。盲目使用替換后可能會導(dǎo)致預(yù)期意外的結(jié)果。有鑒于此,還是建議使用字符串,布爾和數(shù)字類型的數(shù)據(jù)類型。像使用這種下劃線命名約定在一個開源項目中,命名規(guī)則很難維持得一直很好,這樣經(jīng)常會造成一些困擾。

今天群里有小伙伴跟我聊天,問了我?guī)讉€關(guān)于ES6的問題,我才意識到,大部分初學(xué)者在學(xué)習的過程中,都是學(xué)了HTML/CSS/JS之后就開始上手學(xué)習框架了,而對于ES6的重視程度卻不是那么足,或是僅僅了解部分ES6的用法。
由于本項目將會用到大部分ES6的新特性,為避免將來有小伙伴看不懂還得去查,今天這篇就多帶帶為我們之后的開發(fā)做一下ES6的知識儲備。
用 let / const 來代替 var

因為 JavaScript 的 var 關(guān)鍵字是聲明全局的變量,所以在 ES6 中引入了兩個新的變量聲明來解決這個問題,即 let 和 const 。

它們都用于聲明變量。 區(qū)別在于 const 在聲明后不能改變它的值,而 let 則可以。

和 var 不一樣的是,let 和 const 不存在變量提升。

一個 var 的例子:

var snack = "Meow Mix";

function getFood(food) {
    if (food) {
        var snack = "Friskies";
        return snack;
    }
    return snack;
}

getFood(false); // undefined

使用 let 替換了 var 后的表現(xiàn):

let snack = "Meow Mix";

function getFood(food) {
    if (food) {
        let snack = "Friskies";
        return snack;
    }
    return snack;
}

getFood(false); // "Meow Mix"

當我們重構(gòu)使用 var 的老代碼時,一定要注意這種變化。

盲目使用 let 替換 var 后可能會導(dǎo)致預(yù)期意外的結(jié)果。

注意letconst 是塊級作用域語句。所以在語句塊以外引用這些變量時,會造成引用錯誤 ReferenceError

console.log(x);

let x = "hi"; // ReferenceError: x is not defined
在本項目中,將使用 let 聲明一個變量,使用 const 來聲明一個不可改變的常量。
用塊級作用域代替 IIFES

我們以往創(chuàng)建一個 立即執(zhí)行函數(shù) 時,一般是在函數(shù)最外層包裹一層括號。
ES6支持塊級作用域,我們現(xiàn)在可以通過創(chuàng)建一個代碼塊(Block)來實現(xiàn),不必通過創(chuàng)建一個函數(shù)來實現(xiàn),

(function () {
    var food = "Meow Mix";
}());

console.log(food); // Reference Error

使用支持塊級作用域的ES6的版本:

{
    let food = "Meow Mix";
};

console.log(food); // Reference Error
箭頭函數(shù)

有些時候,我們在函數(shù)嵌套中需要訪問上下文中的 this。比如下面的例子:

function Person(name) {
    this.name = name;
}

Person.prototype.prefixName = function (arr) {
    return arr.map(function (character) {
        return this.name + character; // Cannot read property "name" of undefined
    });
};

一種通用的方式是把上下文中的 this 保存在一個變量里:

function Person(name) {
    this.name = name;
}

Person.prototype.prefixName = function (arr) {
    var that = this; // Store the context of this
    return arr.map(function (character) {
        return that.name + character;
    });
};

我們也可以把 this 通過屬性傳進去:

function Person(name) {
    this.name = name;
}

Person.prototype.prefixName = function (arr) {
    return arr.map(function (character) {
        return this.name + character;
    }, this);
};

還可以直接使用 bind

function Person(name) {
    this.name = name;
}

Person.prototype.prefixName = function (arr) {
    return arr.map(function (character) {
        return this.name + character;
    }.bind(this));
};

而如果使用 箭頭函數(shù)this 的值不用我們再做如上幾段代碼的特殊處理,直接使用即可。
上面的代碼可以重寫為下面這樣:

function Person(name) {
    this.name = name;
}

Person.prototype.prefixName = function (arr) {
    return arr.map(character => this.name + character);
};
當你需要維護一個 this 上下文的時候盡量使用 箭頭函數(shù)。

當我們編寫只返回一個表達式值的簡單函數(shù)時,也可以使用箭頭函數(shù),如下:

var squares = arr.map(function (x) { return x * x }); // Function Expression
const arr = [1, 2, 3, 4, 5];
const squares = arr.map(x => x * x); // Arrow Function for terser implementation
字符串

在ES6中,字符串對象新增了 .includes().repeat() 方法。

.includes( )
var string = "food";
var substring = "foo";

console.log(string.indexOf(substring) > -1);

現(xiàn)在,我們可以使用 .inclues() 方法,替代以往判斷內(nèi)容 > -1 的方式。
.includes() 方法會極簡地返回一個布爾值結(jié)果。

const string = "food";
const substring = "foo";

console.log(string.includes(substring)); // true
.repeat()
function repeat(string, count) {
    var strings = [];
    while(strings.length < count) {
        strings.push(string);
    }
    return strings.join("");
}

在ES6中,我們可以使用一個極簡的方法來實現(xiàn)重復(fù)字符:

// String.repeat(numberOfRepetitions)
"meow".repeat(3); // "meowmeowmeow"
字符串模版字面量

使用 字符串模板字面量,我可以在字符串中直接使用特殊字符,而不用轉(zhuǎn)義。

var text = "This string contains "double quotes" which are escaped.";
let text = `This string contains "double quotes" which don"t need to be escaped anymore.`;

字符串模板字面量 還支持直接插入變量,可以實現(xiàn)字符串與變量的直接連接輸出。

var name = "Tiger";
var age = 13;

console.log("My cat is named " + name + " and is " + age + " years old.");

更簡單的版本:

const name = "Tiger";
const age = 13;

console.log(`My cat is named ${name} and is ${age} years old.`);

ES5中,我們要這樣生成多行文本:

var text = (
    "cat
" +
    "dog
" +
    "nickelodeon"
);

或者:

var text = [
    "cat",
    "dog",
    "nickelodeon"
].join("
");

字符串模板字面量 讓我們不必特別關(guān)注多行字符串中的換行轉(zhuǎn)義符號,直接換行即可:

let text = ( `cat
dog
nickelodeon`
);

字符串模板字面量 內(nèi)部可以使用表達式,像這樣:

let today = new Date();
let text = `The time and date is ${today.toLocaleString()}`;
解構(gòu)

解構(gòu)讓我們可以使用非常便捷的語法,直接將數(shù)組或者對象中的值直接分別導(dǎo)出到多個變量中,

解構(gòu)數(shù)組

解構(gòu)數(shù)組

var arr = [1, 2, 3, 4];
var a = arr[0];
var b = arr[1];
var c = arr[2];
var d = arr[3];
let [a, b, c, d] = [1, 2, 3, 4];

console.log(a); // 1
console.log(b); // 2
解構(gòu)對象

解構(gòu)對象

var luke = { occupation: "jedi", father: "anakin" };
var occupation = luke.occupation; // "jedi"
var father = luke.father; // "anakin"
let luke = { occupation: "jedi", father: "anakin" };
let {occupation, father} = luke;

console.log(occupation); // "jedi"
console.log(father); // "anakin"
模塊

ES6之前,瀏覽器端的模塊化代碼,我們使用像Browserify這樣的庫,
Node.js 中,我們則使用 require。
在ES6中,我們現(xiàn)在可以直接使用AMD 和 CommonJS這些模塊了。

使用 CommonJS 的出口
module.exports = 1;
module.exports = { foo: "bar" };
module.exports = ["foo", "bar"];
module.exports = function bar () {};
使用 ES6 的出口

在ES6中,提供了多種設(shè)置模塊出口的方式,比如我們要導(dǎo)出一個變量,那么使用 變量名

export let name = "David";
export let age  = 25;??

還可以為對象 導(dǎo)出一個列表

function sumTwo(a, b) {
    return a + b;
}

function sumThree(a, b, c) {
    return a + b + c;
}

export { sumTwo, sumThree };

我們也可以使用簡單的一個 export 關(guān)鍵字來導(dǎo)出一個結(jié)果值:

export function sumTwo(a, b) {
    return a + b;
}

export function sumThree(a, b, c) {
    return a + b + c;
}

最后,我們可以 導(dǎo)出一個默認出口

function sumTwo(a, b) {
    return a + b;
}

function sumThree(a, b, c) {
    return a + b + c;
}

let api = {
    sumTwo,
    sumThree
};

export default api;

/*
 * 與以下的語句是對等的:
 * export { api as default };
 */
實踐:總是在模塊的 最后 使用 export default 方法。
它讓模塊的出口更清晰明了,節(jié)省了閱讀整個模塊來尋找出口的時間。
更多的是,在大量CommonJS模塊中,通用的習慣是設(shè)置一個出口值或者出口對象。
堅持這個規(guī)則,可以讓我們的代碼更易讀,且更方便的聯(lián)合使用CommonJS和ES6模塊。
ES6 中的導(dǎo)入

ES6提供了好幾種模塊的導(dǎo)入方式。我們可以多帶帶引入一個文件:

import "underscore";
這里需要注意的是, 整個文件的引入方式會執(zhí)行該文件內(nèi)的最上層代碼

就像Python一樣,我們還可以命名引用:

import { sumTwo, sumThree } from "math/addition";

我們甚至可以使用 as 給這些模塊重命名:

import {
    sumTwo as addTwoNumbers,
    sumThree as sumThreeNumbers
} from "math/addition";

另外,我們能 引入所有的東西 (也稱為命名空間引入)

import * as util from "math/addition";

最后,我們能可以從一個模塊的眾多值中引入一個列表:

import * as additionUtil from "math/addtion";
const { sumTwo, sumThree } = additionUtil;

像這樣引用默認對象:

import api from "math/addition";
// Same as: import { default as api } from "math/addition";

我們建議一個模塊導(dǎo)出的值應(yīng)該越簡潔越好,不過有時候有必要的話命名引用和默認引用可以混著用。如果一個模塊是這樣導(dǎo)出的:

// foos.js
export { foo as default, foo1, foo2 };

那我們可以如此導(dǎo)入這個模塊的值:

import foo, { foo1, foo2 } from "foos";

我們還可以導(dǎo)入commonjs模塊,例如React:

import React from "react";
const { Component, PropTypes } = React;

更簡化版本:

import React, { Component, PropTypes } from "react";
注意:被導(dǎo)出的值是被 綁定的,而不是引用。
所以,改變一個模塊中的值的話,會影響其他引用本模塊的代碼,一定要避免此種改動發(fā)生。
參數(shù)

在ES5中,許多種方法來處理函數(shù)的 參數(shù)默認值(default values)參數(shù)數(shù)量(indefinite arguments),參數(shù)命名(named parameters)
ES6中,我們可以使用非常簡潔的語法來處理上面提到的集中情況。

默認參數(shù)
function addTwoNumbers(x, y) {
    x = x || 0;
    y = y || 0;
    return x + y;
}

ES6中,我們可以簡單為函數(shù)參數(shù)啟用默認值:

function addTwoNumbers(x=0, y=0) {
    return x + y;
}
addTwoNumbers(2, 4); // 6
addTwoNumbers(2); // 2
addTwoNumbers(); // 0
rest 參數(shù)

ES5中,遇到參數(shù)數(shù)量不確定時,我們只能如此處理:

function logArguments() {
    for (var i=0; i < arguments.length; i++) {
        console.log(arguments[i]);
    }
}

使用 rest 操作符,我們可以給函數(shù)傳入一個不確定數(shù)量的參數(shù)列表:

function logArguments(...args) {
    for (let arg of args) {
        console.log(arg);
    }
}
命名參數(shù)

命名函數(shù)
ES5中,當我們要處理多個 命名參數(shù) 時,通常會傳入一個 選項對象 的方式,這種方式被jQuery采用。

function initializeCanvas(options) {
    var height = options.height || 600;
    var width  = options.width  || 400;
    var lineStroke = options.lineStroke || "black";
}

我們可以利用上面提到的新特性 解構(gòu) ,來完成與上面同樣功能的函數(shù):
We can achieve the same functionality using destructuring as a formal parameter
to a function:

function initializeCanvas(
    { height=600, width=400, lineStroke="black"}) {
        // ...
    }
    // Use variables height, width, lineStroke here

如果我們需要把這個參數(shù)變?yōu)榭蛇x的,那么只要把該參數(shù)解構(gòu)為一個空對象就好了:

function initializeCanvas(
    { height=600, width=400, lineStroke="black"} = {}) {
        // ...
    }
展開操作

我們可以利用展開操作符(Spread Operator)來把一組數(shù)組的值,當作參數(shù)傳入:

Math.max(...[-1, 100, 9001, -32]); // 9001
類 Classes

在ES6以前,我們實現(xiàn)一個類的功能的話,需要首先創(chuàng)建一個構(gòu)造函數(shù),然后擴展這個函數(shù)的原型方法,就像這樣:

function Person(name, age, gender) {
    this.name   = name;
    this.age    = age;
    this.gender = gender;
}

Person.prototype.incrementAge = function () {
    return this.age += 1;
};

繼承父類的子類需要這樣:

function Personal(name, age, gender, occupation, hobby) {
    Person.call(this, name, age, gender);
    this.occupation = occupation;
    this.hobby = hobby;
}

Personal.prototype = Object.create(Person.prototype);
Personal.prototype.constructor = Personal;
Personal.prototype.incrementAge = function () {
    return Person.prototype.incrementAge.call(this) += 20;
};

ES6提供了一些語法糖來實現(xiàn)上面的功能,我們可以直接創(chuàng)建一個類:

class Person {
    constructor(name, age, gender) {
        this.name   = name;
        this.age    = age;
        this.gender = gender;
    }

    incrementAge() {
      this.age += 1;
    }
}

繼承父類的子類只要簡單的使用 extends 關(guān)鍵字就可以了:

class Personal extends Person {
    constructor(name, age, gender, occupation, hobby) {
        super(name, age, gender);
        this.occupation = occupation;
        this.hobby = hobby;
    }

    incrementAge() {
        super.incrementAge();
        this.age += 20;
        console.log(this.age);
    }
}
實踐:ES6新的類語法把我們從晦澀難懂的實現(xiàn)和原型操作中解救出來,這是個非常適合初學(xué)者的功能,而且能讓我們寫出更干凈整潔的代碼。
Symbols

Symbols在ES6版本之前就已經(jīng)存在了,但現(xiàn)在我們擁有一個公共的接口來直接使用它們。
Symbols是不可更改的(immutable)并且唯一的(unique),它可用作任何hash數(shù)據(jù)類型中的鍵。

Symbol()

調(diào)用 Symbol() 或者 Symbol(描述文本) 會創(chuàng)建一個唯一的、在全局中不可以訪問的Symbol對象。
一個 Symbol() 的應(yīng)用場景是:在自己的項目中使用第三方代碼庫,且你需要給他們的對象或者命名空間打補丁代碼,又不想改動或升級第三方原有代碼的時候。
例如,如果你想給 React.Component 這個類添加一個 refreshComponent 方法,但又確定不了這個方法會不會在下個版本中加入,你可以這么做:

const refreshComponent = Symbol();

React.Component.prototype[refreshComponent] = () => {
    // do something
}
Symbol.for(key)

使用 Symbol.for(key) 也是會創(chuàng)建一個不可改變的Symbol對象,但區(qū)別于上面的創(chuàng)建方法,這個對象是在全局中可以被訪問到的。
兩次相同的 Symbol.for(key) 調(diào)用會返回相同的Symbol實例。

提示:這并不同于 Symbol(description)。

Symbol("foo") === Symbol("foo") // false
Symbol.for("foo") === Symbol("foo") // false
Symbol.for("foo") === Symbol.for("foo") // true

Symbols常用的一個使用場景,尤其是使用 Symbol.for(key) 方法,是用于實現(xiàn)代碼間的互操作。
在你的代碼中,通過在包含一些已知接口的第三方庫的對象參數(shù)中查找Symbol成員,你可以實現(xiàn)這種互操作。
例如:

function reader(obj) {
    const specialRead = Symbol.for("specialRead");
    if (obj[specialRead]) {
        const reader = obj[specialRead]();
        // do something with reader
    } else {
        throw new TypeError("object cannot be read");
    }
}

之后在另一個庫中:

const specialRead = Symbol.for("specialRead");

class SomeReadableType {
    [specialRead]() {
        const reader = createSomeReaderFrom(this);
        return reader;
    }
}
注意:關(guān)于Symbol互操作的使用,一個值得一提的例子是Symbol.iterableSymbol.iterable存在ES6的所有可枚舉對象中:數(shù)組(Arrays)、
字符串(strings)、生成器(Generators)等等。當它作為一個方法被調(diào)用時,它將會返回一個帶有枚舉接口的對象。
Maps

Maps 是一個JavaScript中很重要(迫切需要)的數(shù)據(jù)結(jié)構(gòu)。
在ES6之前,我們創(chuàng)建一個 hash 通常是使用一個對象:

var map = new Object();
map[key1] = "value1";
map[key2] = "value2";

但是,這樣的代碼無法避免函數(shù)被特別的屬性名覆蓋的意外情況:

> getOwnProperty({ hasOwnProperty: "Hah, overwritten"}, "Pwned");
> TypeError: Property "hasOwnProperty" is not a function

Maps 讓我們使用 set,getsearch 操作數(shù)據(jù)。

let map = new Map();
> map.set("name", "david");
> map.get("name"); // david
> map.has("name"); // true

Maps最強大的地方在于我們不必只能使用字符串來做key了,現(xiàn)在可以使用任何類型來當作key,而且key不會被強制類型轉(zhuǎn)換為字符串。

let map = new Map([
    ["name", "david"],
    [true, "false"],
    [1, "one"],
    [{}, "object"],
    [function () {}, "function"]
]);

for (let key of map.keys()) {
    console.log(typeof key);
    // > string, boolean, number, object, function
}
提示:當使用 map.get() 判斷值是否相等時,非基礎(chǔ)類型比如一個函數(shù)或者對象,將不會正常工作。
有鑒于此,還是建議使用字符串,布爾和數(shù)字類型的數(shù)據(jù)類型。

我們還可以使用 .entries() 方法來遍歷整個map對象:

for (let [key, value] of map.entries()) {
    console.log(key, value);
}
WeakMaps

在ES5之前的版本,我們?yōu)榱舜鎯λ接袛?shù)據(jù),有好幾種方法。像使用這種下劃線命名約定:

class Person {
    constructor(age) {
        this._age = age;
    }

    _incrementAge() {
        this._age += 1;
    }
}

在一個開源項目中,命名規(guī)則很難維持得一直很好,這樣經(jīng)常會造成一些困擾。
此時,我們可以選擇使用WeakMaps來替代Maps來存儲我們的數(shù)據(jù):

let _age = new WeakMap();
class Person {
    constructor(age) {
        _age.set(this, age);
    }

    incrementAge() {
        let age = _age.get(this) + 1;
        _age.set(this, age);
        if (age > 50) {
            console.log("Midlife crisis");
        }
    }
}

使用WeakMaps來保存我們私有數(shù)據(jù)的理由之一是不會暴露出屬性名,就像下面的例子中的 Reflect.ownKeys()

> const person = new Person(50);
> person.incrementAge(); // "Midlife crisis"
> Reflect.ownKeys(person); // []

一個使用WeakMaps存儲數(shù)據(jù)更實際的例子,是存儲與DOM元素相關(guān)聯(lián)的數(shù)據(jù),而這不會對DOM元素本身產(chǎn)生污染:

let map = new WeakMap();
let el  = document.getElementById("someElement");

// Store a weak reference to the element with a key
map.set(el, "reference");

// Access the value of the element
let value = map.get(el); // "reference"

// Remove the reference
el.parentNode.removeChild(el);
el = null;

value = map.get(el); // undefined

上面的例子中,一旦對象被垃圾回收器給銷毀了,WeakMaps會自動的把這個對象所對應(yīng)的鍵值對數(shù)據(jù)同時銷毀。

提示:結(jié)合這個例子,再考慮下jQuery是如何實現(xiàn)緩存帶有引用的DOM元素這個功能的。使用WeakMaps的話,當被緩存的DOM元素被移除的時,jQuery可以自動釋放相應(yīng)元素的內(nèi)存。
通常情況下,在涉及DOM元素存儲和緩存的情況下,使用WeakMaps是非常有效的。
Promises

Promises讓我們把多縮進難看的代碼(回調(diào)地獄):

func1(function (value1) {
    func2(value1, function (value2) {
        func3(value2, function (value3) {
            func4(value3, function (value4) {
                func5(value4, function (value5) {
                    // Do something with value 5
                });
            });
        });
    });
});

寫成這樣:

func1(value1)
    .then(func2)
    .then(func3)
    .then(func4)
    .then(func5, value5 => {
        // Do something with value 5
    });

在ES6之前,我們使用bluebird 或者
Q?,F(xiàn)在我們有了原生版本的 Promises:

new Promise((resolve, reject) =>
    reject(new Error("Failed to fulfill Promise")))
        .catch(reason => console.log(reason));

這里有兩個處理函數(shù),resolve(當Promise執(zhí)行成功完畢時調(diào)用的回調(diào)函數(shù)) 和 reject (當Promise執(zhí)行不接受時調(diào)用的回調(diào)函數(shù))

Promises的好處:大量嵌套錯誤處理回調(diào)函數(shù)會使代碼變得難以閱讀理解。
使用Promises,我們可以通過清晰的路徑將錯誤事件讓上傳遞,并且適當?shù)靥幚硭鼈儭?br>此外,Promise處理后的值,無論是解決(resolved)還是拒絕(rejected)的結(jié)果值,都是不可改變的。

下面是一些使用Promises的實際例子:

var request = require("request");

return new Promise((resolve, reject) => {
  request.get(url, (error, response, body) => {
    if (body) {
        resolve(JSON.parse(body));
      } else {
        resolve({});
      }
  });
});

我們還可以使用 Promise.all()并行化 的處理一組異步的操作。

let urls = [
  "/api/commits",
  "/api/issues/opened",
  "/api/issues/assigned",
  "/api/issues/completed",
  "/api/issues/comments",
  "/api/pullrequests"
];

let promises = urls.map((url) => {
  return new Promise((resolve, reject) => {
    $.ajax({ url: url })
      .done((data) => {
        resolve(data);
      });
  });
});

Promise.all(promises)
  .then((results) => {
    // Do something with results of all our promises
 });
Generators 生成器

就像Promises如何讓我們避免回調(diào)地獄一樣,Generators也可以使我們的代碼扁平化,同時給予我們開發(fā)者像開發(fā)同步代碼一樣的感覺來寫異步代碼。Generators本質(zhì)上是一種支持的函數(shù),隨后返回表達式的值。
Generators實際上是支持暫停運行,隨后根據(jù)上一步的返回值再繼續(xù)運行的一種函數(shù)。

下面代碼是一個使用generators函數(shù)的簡單例子:

function* sillyGenerator() {
    yield 1;
    yield 2;
    yield 3;
    yield 4;
}

var generator = sillyGenerator();
> console.log(generator.next()); // { value: 1, done: false }
> console.log(generator.next()); // { value: 2, done: false }
> console.log(generator.next()); // { value: 3, done: false }
> console.log(generator.next()); // { value: 4, done: false }

就像上面的例子,當next運行時,它會把我們的generator向前“推動”,同時執(zhí)行新的表達式。
我們能利用Generators來像書寫同步代碼一樣書寫異步代碼。

// Hiding asynchronousity with Generators

function request(url) {
    getJSON(url, function(response) {
        generator.next(response);
    });
}

這里我們寫個generator函數(shù)將要返回我們的數(shù)據(jù):

function* getData() {
    var entry1 = yield request("http://some_api/item1");
    var data1  = JSON.parse(entry1);
    var entry2 = yield request("http://some_api/item2");
    var data2  = JSON.parse(entry2);
}

借助于 yield,我們可以保證 entry1 確實拿到數(shù)據(jù)并轉(zhuǎn)換后再賦值給 data1。

當我們使用generators來像書寫同步代碼一樣書寫我們的異步代碼邏輯時,沒有一種清晰簡單的方式來處理期間可能會產(chǎn)生的錯誤或者異常。在這種情況下,我們可以在我們的generator中引入Promises來處理,就像下面這樣:

function request(url) {
    return new Promise((resolve, reject) => {
        getJSON(url, resolve);
    });
}

我們再寫一個函數(shù),其中使用 next 來步進我們的generator的同事,再利用我們上面的 request 方法來產(chǎn)生(yield)一個Promise。

function iterateGenerator(gen) {
    var generator = gen();
    var ret;
    (function iterate(val) {
        ret = generator.next();
        if(!ret.done) {
            ret.value.then(iterate);
        }
    })();
}

在Generator中引入了Promises后,我們就可以通過Promise的 .catchreject 來捕捉和處理錯誤了。
使用了我們新版的Generator后,新版的調(diào)用就像老版本一樣簡單可讀(譯者注:有微調(diào)):

iterateGenerator(function* getData() {
    var entry1 = yield request("http://some_api/item1");
    var data1  = JSON.parse(entry1);
    var entry2 = yield request("http://some_api/item2");
    var data2  = JSON.parse(entry2);
});

在使用Generator后,我們可以重用我們的老版本代碼實現(xiàn),以此展示了Generator的力量。
當使用Generators和Promises后,我們可以像書寫同步代碼一樣書寫異步代碼的同時優(yōu)雅地解決了錯誤處理問題。
此后,我們實際上可以開始利用更簡單的一種方式了,它就是async-await。

Async Await

async await 給我們提供了一種更輕松的、更簡單的可以替代的實現(xiàn)上面 Generators 配合 Promises 組合代碼的一種編碼方式,讓我們來看看例子:

var request = require("request");

function getJSON(url) {
  return new Promise(function(resolve, reject) {
    request(url, function(error, response, body) {
      resolve(body);
    });
  });
}

async function main() {
  var data = await getJSON();
  console.log(data); // NOT undefined!
}

main();

它們看上去和Generators很像。我強烈推薦使用 async await 來替代Generators + Promises的寫法。

Getter/Setter 函數(shù)

ES6 實現(xiàn)了 getter 和 setter 函數(shù),比如下面這個例子:

class Employee {
    constructor(name) {
        this._name = name;
    }
    get name() {
      if(this._name) {
        return "Mr. " + this._name.toUpperCase();  
      } else {
        return undefined;
      }  
    }
    set name(newName) {
      if (newName == this._name) {
        console.log("I already have this name.");
      } else if (newName) {
        this._name = newName;
      } else {
        return false;
      }
    }
    }
var emp = new Employee("James Bond");
if (emp.name) {
  console.log(emp.name);  
  }
emp.name = "Bond 007";
console.log(emp.name);  

瀏覽器也在對象中實現(xiàn)了 getter 和 setter 函數(shù),我們可以使用它們來實現(xiàn) 計算屬性,在設(shè)置和獲取一個屬性之前加上監(jiān)聽器和處理。

var person = {
  firstName: "James",
  lastName: "Bond",
  get fullName() {
      console.log("Getting FullName");
      return this.firstName + " " + this.lastName;
  },
  set fullName (name) {
      console.log("Setting FullName");
      var words = name.toString().split(" ");
      this.firstName = words[0] || "";
      this.lastName = words[1] || "";
  }
  }
person.fullName; 
person.fullName = "Bond 007";
person.fullName; 
總結(jié)

雖然我們不使用ES6依然能完成整個項目,但能熟練使用ES6新特性,將會是代碼更簡潔優(yōu)雅。

所以,盡快把ES6的知識掌握了吧。記得點好看呦!

本系列文章目錄:

用vue-cli3從0到1做一個完整功能手機站(一)

從0到1開發(fā)實戰(zhàn)手機站(二):Git提交規(guī)范配置

從0到1使用VUE-CLI3開發(fā)實戰(zhàn)(三): ES6知識儲備

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/101167.html

相關(guān)文章

  • 新手福音!用vue-cli301做一個完整功能手機站(一)

    摘要:開篇從今天起,小肆將和大家從頭開始做一個完整的實戰(zhàn)項目。關(guān)注技術(shù)放肆聊跟小肆一起行動起來在這個項目中,小肆力爭做到以下幾點應(yīng)用目前最新的技術(shù),并隨時間更新。 開篇 從今天起,小肆將和大家從頭開始做一個完整的實戰(zhàn)項目。其中遇到的每個知識點都是我們工作中常見的,這些知識點大多在網(wǎng)上都能找到但卻沒有哪個教程能都講得到,那就由小肆來做吧。 關(guān)注技術(shù)放肆聊,跟小肆一起行動起來! 在這個項目中,小...

    stefan 評論0 收藏0
  • 01使用VUE-CLI3開發(fā)實戰(zhàn)(五):模塊化VUEX及使用vuetify

    摘要:小肆前幾天發(fā)了一篇年精品開源項目庫的匯總,今天小肆要使用的是在組件中排行第三的。記得點好看呦前置閱讀用從到做一個完整功能手機站一從到開發(fā)實戰(zhàn)手機站二提交規(guī)范配置從到使用開發(fā)實戰(zhàn)三知識儲備從到使用開發(fā)實戰(zhàn)四封裝 小肆前幾天發(fā)了一篇2019年Vue精品開源項目庫的匯總,今天小肆要使用的是在UI組件中排行第三的Vuetify。 vuetify介紹 Vuetify是一個漸進式的框架,完全根據(jù)M...

    fuyi501 評論0 收藏0
  • 前端最實用書簽(持續(xù)更新)

    摘要:前言一直混跡社區(qū)突然發(fā)現(xiàn)自己收藏了不少好文但是管理起來有點混亂所以將前端主流技術(shù)做了一個書簽整理不求最多最全但求最實用。 前言 一直混跡社區(qū),突然發(fā)現(xiàn)自己收藏了不少好文但是管理起來有點混亂; 所以將前端主流技術(shù)做了一個書簽整理,不求最多最全,但求最實用。 書簽源碼 書簽導(dǎo)入瀏覽器效果截圖showImg(https://segmentfault.com/img/bVbg41b?w=107...

    sshe 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<