简答
一.谈谈你是如何理解js异步编程的,EventLoop,消息队列都是做什么的,什么是宏任务,什么是微任务?
1.采用单线程工作的原因
js这门语言刚刚创建出来的时候的特点就是单线程,用来实现页面上的交互,实现交互的核心就是dom操作,必须为单线程,否则就会出现线程同步问题(如删除、移动一起执行),浏览器不知道以哪个线程 为准
单线程是指js执行环境中负责执行代码的线程只有一个
JavaScript是单线程的,但浏览器不是单线程,例如JavaScript的api,如倒计时器
所有的异步编程方案的根基就是回调函数
缺点:有一步耗时的任务会出现阻塞
为了解决这个问题,JavaScript将任务的执行模式分为同步模式和异步模式
2.异步编程
1.不会等待这个任务的结束才开始下一个任务,开启之后就立即往后执行下一个任务
2.能解决处理大量耗时任务
3.代码执行顺序混乱
3.EventLoop,消息队列
EventLoop监听调用栈和消息队列,当调用栈中的任务结束后,EventLoop就会从消息队列中取出第一个回调函数压入到调用栈当中执行、
js代码调用线程开始异步代码,
4.什么是宏任务,什么是微任务
宏任务表示比较大的异步任务,会排到消息队列最后,为api的执行任务
微任务表示小的任务,属于额外的小任务,会排到调用栈的执行完的第一个 如promise
js在完成主线程之后,会依次执行消息队列当中的任务
代码
一 将下面异步代码使用promise的方式改进
setTimeout(function () {
var a = 'hello'
setTimeout(function(){
var b = 'lagou'
setTimeout(function(){
var c = '(๑′ᴗ‵๑)I Lᵒᵛᵉᵧₒᵤ❤'
console.log(a+b+c)
},10)
},10)
},10);
var promise = Promise.resolve('hello')
.then(value=>{
var b = 'lagou'
return value + b
})
.then(value=>{
var c = '(๑′ᴗ‵๑)I Lᵒᵛᵉᵧₒᵤ❤'
console.log(value + c)
})
二、基于以下代码完成下面的四个练习
const fp = require('lodash/fp')
// 数据
// 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: 'Jagura 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: 185000, in_stock: true },
{ name: 'Pagani Huayra', horsepower: 700, dollar_value: 130000, in_stock: false }
]
1.使用函数组合fp.flowRight()实现下面这个函数
let isLastInStock = function(cars){
// 获取最后一条数据
let last_car = fp.last(cars)
// 获取最后一条数据的 in_stock 属性值
return fp.prop('in_stock',last_car)
}
let isLastInStock = fp.flowRight(fp.prop('in_stock'),fp.last)
let value = isLastInStock(cars)
console.log(value)
2.使用fp.flowRight() fp.prop fp.first 获取第一个car的name
let getFirstName = fp.flowRight(fp.prop('name'),fp.first)
let value = getFirstName(cars)
console.log(value)
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)
}
let averageDollarValue = fp.flowRight(_average,fp.map(car=>car.dollar_value))
console.log(averageDollarValue(cars))
4.使用flowRight写一个sanitizeNames()函数,返回一个下划线连接的小写字符串,把数组的name转换为这种格式
// 例如:sanitizeNames['Hello World']=>['hello_word']
let _underscore = fp.replace(/\W+/g,'_')
let sanitizeNames = fp.flowRight(fp.map(fp.flowRight(_underscore,fp.toLower)))
console.log(sanitizeNames(['Hello World']))
三、基于下面提供的代码,完成后续的四个练习
// support.js
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(x){
return new Maybe(x)
}
isNothing(){
return this._value === null || this._value === undefined
}
constructor(x){
this._value = x
}
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
const {Maybe,Container} = require('./support')
let maybe = Maybe.of([5,6,1,'a',undefined])
let ex1 = (x)=>{
return maybe.map(fp.map(fp.add(x)))
}
console.log(ex1(1))
2.实现一个函数ex2能够使用fp.first获取列表的第一个元素
let xs = Container.of(['do', 'ray', 'me', 'fa', 'so', 'la', 'ti', 'do'])
let ex2 = () => {
return xs.map(fp.first)._value
}
console.log(ex2())
3.实现一个函数 ex3,使用safeProp和fp.first找到user的名字的首字母
let safeProp = fp.curry(function (x, o) {
return Maybe.of(o[x])
})
let user = { id: 2, name: 'Albert' }
let ex3 = () => {
return safeProp('name')(user).map(fp.first)._value
}
console.log(ex3())
4.使用Maybe重写ex4,不要有if语句
let ex4 = function(n){
if(n){
return parseInt(n)
}
}
let ex4 = function(n) {
return Maybe.of(n).map(parseInt)._value
}
console.log(ex4(null))