函数式编程代码篇
##
谈谈你是如何理解JS异步编程的,EventLoop、消息队列都是做什么的,什么是宏任务,什么是微任务?
谈到异步编程,我们就会想到同步,首先来说说同步是什么吧。同步:就比如蒸包子,只有等包子蒸熟之后才可以炒菜,这样一件事做完才可以做下一件事的事件就是同步。那么异步呢,就是在蒸包子等待的时间可以拿来做其他事情的事件就是异步。
// 同步
let a = 1
let b = 2
console.log(a)
console.log(b)
// 异步
setTimeout(function addFn(){
return a + b
},1000)
console.log(a)
EventLoop事件循环和消息队列:同步的事件会被放到主线程执行栈中去执行,异步的事件会被放进消息队列,当执行栈中的任务执行完之后,js引擎会到消息队列中去看是否有任务,如果有任务,把任务放到执行栈,这种循环检视的行为就是事件循环
宏任务: 浏览器和node环境中,事件有setTimeout,setInterval,setImmediate等
微任务:js引擎,事件有Promise,MutationObserver,process.nextTick等
微任务先于宏任务执行
一、将下面异步代码使用promise的方式改进
setTimeout(function() {
var a = 'hello';
setTimeout(function() {
var b = 'lagou';
setTimeout(function() {
var c = 'I ❤ U';
console.log(a + b + c);
}, 10);
}, 10);
}, 10);
Promise.resole().then(()=>{
let a = 'hello'
return a
}).then(res => {
let b = 'lagou'
return res + b
}).then(res => {
let c = 'I ❤ U'
console.log(res + c)
})
二、基于以下代码完成下面的四个练习
// 数据
// horsepower 马力, dollar_value价格,in_stock 库存
const cars = [
{
name: 'Ferrari FF', horsepower: 660, dollar_value: 700000, in_stock: true
},
{
name: 'Spyker C12 Zagato', horsepower: 650, dollar_value: 648000, in_stock: false
},
{
name: 'Jaguar XKR-S', horsepower: 550, dollar_value: 132000, in_stock: false
},
{
name: 'Audi R8', horsepower: 525, dollar_value: 114200, in_stock: false
},
{
name: 'Aston Martin One-77', horsepower: 750, dollar_value: 1850000, in_stock: true
},
{
name: 'Pagani Huayra', horsepower: 700, dollar_value: 1300000, in_stock: false
}
]
练习1:使用函数组合 fp.flowRight()重新实现下面这个函数
const fp = require('lodash/fp')
const f = fp.flowRight(fp.join('-'),fp.map(_.toLower),fp.split(' '))
console.log(f('NEVER SAY DIE'))
const last_stock = s => fp.prop('in_stock', s)
const get_car= cars => cars.reserve()
const last_car = arr => arr[0]
const car = fp.flowRight(last_stock,last_car,get_car)
car(cars)
练习2:使用fp.flowRight(),fp.prop(),fp.first()获取第一个car的name
let first = cars => fp.first(cars)
let name = cars => fp.prop('name',cars)
let f = fp.flowRight(name,first)
f(cars)
练习3:使用帮助函数_average重构averageDollarValue,使用函数组合的方式实现
let _average = function (xs) {
return fp.reduce(fp.add,0,xs)/xs.length
}
let averageDollarValue = function (cars) {
let dollar_values = fp.map(function(car){
return car.dollar_value
},cars)
return _average(dollar_values)
}
练习4: 使用flowRight 写一个sanitizeNames()函数,返回一个下划线连结的小写字符串,把数组中的name转换为这种形式:例如:sanitizeNames(['Hello World']) => ['hello_world']
let _underscore = fp.replace(/\W+/g,'_') //无须改动,并在sanitizeNames中使用它
let fp = require('./lodash/fp')
let sanitizeNames = fp.flowRight(_underscore)
sanitizeNames(['Hello World'])
三、基于下面提供的代码,完成后续的四个练习
class Container {
static of(value) {
return new Container(value)
}
constructor(value) {
this._value = value
}
map(fn) {
return Container.of(fn(this._value))
}
}
class Maybe {
static of(value) {
return new Maybe(value)
}
constructor(value) {
this._value = value
}
}
isNothing() {
return this._value === null || this._value === undefined
}
map(fn) {
return this.isNothing() ? this : Maybe.of(fn(this._value))
}
module.exports = {Maybe, Container}
练习1: 使用fp.add(x,y) 和fp.map(f,x)创建一个能让functor里的值增加的函数ex1
// app.js
const fp = require('lodash/fp')
const { Maybe,Container } = require('./support')
let maybe = Maybe.of([5,6,1])
let ex1 = () => {
//你需要实现的函数
maybe.map((x,y)=>fp.add(x,y))
}
练习2:实现一个函数ex2,能够使用fp.first 获取列表的第一个元素
// app.js
const fp = require('lodash/fp')
const { Maybe,Container } = require('./support')
let xs = Container.of(['do','ray','me','fa','so','la','ti','do'])
let ex2 = () => {
// 你需要实现的函数
xs.map(fn => {
return fp.first(fn)
})
}
练习3:实现一个函数ex3,使用safeProp和fp.first找到user的名字的首字母
//app.js
const fp = require('lodash/fp')
const {Maybe,Container } = require('./support')
let safeProp = fp.curry(function(x,o){
return Maybe.of(o[x])
})
let user = { id: 2,name: 'Albert'}
let ex3 = () => {
// 你需要实现的函数
let name = safeProp('name',user)
fp.fist(name)
}
练习4:使用Maybe重写ex4,不要由if 语句
// app.js
const fp = require('lodash/fp')
const { Maybe,Container } = require('./support)
let ex4 = function (n) {
if (n) {
return parseInt(n)
}
}
let n = fp.curry(function(n){
return Maybe.of(n)? parseInt(n): n
})
四、手写实现MyPromise源码
要求: 尽可能还原Promise中的每一个API,并通过注释的方式描述思路和原理
// myPromise.js
const PEDDING = 'pedding'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
constructor (excutor) {
excutor(resolve,reject)
}
status = PEDDING
res = undefined
reson = undefined
resolve = res => {
if (this.status !== FULFILLED) return
this.status = FULFILLED
this.res = res
}
reject = reson => {
if (this.status = REJECTED) return
this.status = REJECTED
this.reson = reson
}
then (successCallback,fail)
}
const MyPromise = require('./myPromise')
let promise = new Promise((resolve, reject) => {
resolve('成功')
// reject('失败')
})
promise.then(res => {
console.log(res)
}, reson => {
console.log(reson)
})

浙公网安备 33010602011771号