小结2

9. Set/Map

在此之前,一般用对象属性来模拟set和map两种集合:

// set

var set = Object.create(null)

 

set.foo = true

 

if(set.foo) {

    // do something

}

 

// map

var map = Object.create(null)

map.foo = 'bar'

 

var value = map.foo

console.log(value)

// 'bar'

在 ES6 中新增了有序列表set,其中含有一些相互独立的非重复值,通过set集合可以快速访问其中的数据,更有效地追踪各种离散值。

关于set运用得最多的应该就是去重了:

const arr = [1, 1, 2, 11, 32, 1, 2, 3, 11]

 

const deDuplication = function(arr) {

    return [...(new Set(arr))]

}

 

console.log(deDuplication(arr))

// [1, 2, 11, 32, 3]

在 ES6 中map允许我们队值进行get、set和search操作:

let map = new Map()

 

map.set('name', 'david')

 

map.get('name')

// david

map.has('name')

// true

map不仅限于使用字符串作为 key,还可以用其他任何类型的数据作为 key:

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

10. Weak Set/Weak Map

对于set和WeakSet来说,它们之间最大的区别就是,WeakSet保存的是对象值得弱引用,下面这个实例会展示它们的差异:

let set = new WeakSet(),

    key = {}

 

set.add(key)

console.log(set.has(key))

// true

 

// 移除对象key的最后一个强引用( WeakSet 中的引用也自动移除 )

key = null

 这段代码执行过后,就无法访问WeakSet中 key 的引用了。除了这个,它们还有以下几个差别:

  • 在WeakSet的实例中,如果向add()、has()和delete()这三个方法传入非对象参数都会导致程序报错。
  • WeakSet集合不可迭代,所以不能被用于for-of循环。
  • WeakSet集合不暴露任何迭代器(例如keys()和values()方法),所以无法通过程序本身来检测其中的内容。
  • WeakSet集合不支持forEach()方法。
  • WeakSet集合不支持size属性。

总之如果只需要跟踪对象引用,你更应该使用WeakSet集合而不是普通的set集合。

11. Promise

在 ES6 出现之前,处理异步函数主要是通过回调函数,虽然不错,但是用多之后就会发现嵌套太多回调函数回引起回调地狱,当我们有了 Promise 之后,就可以将这些转化成垂直代码:

func1(value1)

    .then(func2)

    .then(func3)

    .then(func4)

    .then(func5, value5 => {

        // Do something with value 5

    })

原生的 Promise 有两个处理器:resolve(当 Promise 是fulfilled时的回调)和reject(当 Promise 是rejected时的回调):

new Promise((resolve, reject) =>

    reject(new Error('Failed to fulfill Promise')))

        .catch(reason => console.log(reason))

Promise的好处:对错误的处理使用一些列回调会使代码很混乱,使用 Promise,我看可以清晰的让错误冒泡并且在合适的时候处理它,甚至,在 Promise 确定了resolved/rejected之后,他的值是不可改变的——它从来不会变化。

这是使用 Promise 的一个实际的例子:

const request = require('request')

 

return new Promise((resolve, reject) => {

  request.get(url, (error, response, body) => {

    if (body) {

        resolve(JSON.parse(body))

      } else {

        resolve({})

      }

  })

})

12. Generators 生成器

就像 Promise 可以帮我们避免回调地狱,Generator 可以帮助我们让代码风格更整洁——用同步的代码风格来写异步代码,它本质上是一个可以暂停计算并且可以随后返回表达式的值的函数:

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可以回去到下一个yield返回的值,当然上面的代码是非常不自然的,我们可以利用 Generator 来用同步的方式来写异步操作:

function request(url) {

    getJSON(url, function(response) {

        generator.next(response)

    })

}

这里的 generator 函数将会返回需要的数据:

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有data1中我们需要解析并储存的数据。

13. Async Await

async await可以用更少的处理实现 PromiseGenerators 所实现的异步处理:

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()

14. Getter/Setter 函数

ES6 已经开始实现了 getter 和 setter 函数:

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")

 

// uses the get method in the background

if (emp.name) {

  console.log(emp.name)

  // Mr. JAMES BOND

}

 

// uses the setter in the background

emp.name = "Bond 007"

console.log(emp.name)

// Mr. BOND 007

 最新版的浏览器也在对象中实现了getter和setter函数,可以使用它们来实现 计算属性,在设置和获取一个属性之前加上监听器和处理。

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

// James Bond

person.fullName = 'Bond 007'

person.fullName

// Bond 007

 

猜你喜欢

转载自www.cnblogs.com/hjy-21/p/12393084.html