简答题
一、
1.javascript为什么是单线程?
与javascript的设计初衷有关,最早javascript是运行在浏览器中的脚本语言,目的是为了实现页面上的动态交互,实现页面的核心是dom操作,所以决定了javascript是单线程,否则会出现线程同步的问题:
比如多个线程同时操作一个dom元素,这时浏览器不知道要以谁的操作为准,造成代码执行顺序混乱
javascript是单线程也就意味着浏览器有多个任务的时候要排队依次进行,一个一个完成,这种模式的优点是比较安全。缺点是如果我们遇到一个特别消耗时间的任务,那么后面的任务就会一直等着这个任务的完成,这样会造成页面卡死的情况,会造成阻塞。
javascript语言无法处理大量的耗时任务,为了解决这个问题,javascript讲执行任务分成了两种模式:同步模式和异步模式
2.同步模式
同步模式指的是我们的javascript代码要依次执行,后面的代码要等待前一句代码执行完成才能执行,排队执行,javascript代码大多数是以同步模式进行执行的
3.异步模式
异步模式指的是我们的javascript代码不会等待前面的代码执行完毕才开始执行。
我们将执行的代码放入到调用栈中执行,如果是同步的直接执行,如果是异步的则放入消息队列中等待执行,等到所有的代码执行完毕,我们的event loop就上场了,它会监听调用栈和消息队列中的任务,当调用栈中所有的任务结束以后,它会从消息队列中依次取出回调函数压入到调用栈,开始执行,直到整个循环结束
4.Event Loop
主线程从消息队列中读取事件,这个过程是循环不断的,所以整个的这种运行机制称为Event Loop(事件循环),Event Loop是javascript的执行机制
5.消息队列
消息队列是暂时存放异步任务的地方,我们的异步代码会存放到消息队列中,等到同步代码执行完毕以后,event loop会从消息队列中依次取出异步任务放到调用栈中再次执行。
6.宏任务,微任务
宏任务:当前调用栈中执行的代码成为宏任务,包括 主代码快 ,定时器
微任务:宏任务执行完,在下一个宏任务开始之前需要执行的任务,可以理解为回调函数
运行机制:
在执行栈中执行一个宏任务
执行过程中遇到微任务,将微任务添加到消息队列中
当前宏任务执行完毕,立即执行微任务队列中的任务
微任务执行完毕后,把下一个宏任务放到消息队列中,通过eventloop放到调用栈中执行。
代码题
一、
new Promise((resolve, reject) => {
var a = 'hello'
resolve(a)
}).then(value=> {
var b = 'lagou'
return value + b
}).then(value=> {
var c = 'I❤U'
console.log(value + c )
})
二、
练习1:
let isLastInStock = function(cars) {
//获取最后一条数据
let last = cars => cars.pop()
//获取最后一条数据in_stock属性值
let getValue = last => last.in_stock
return fp.flowRight(value, last)
}
练习2:
let isFirstName = function(cars) {
//获取第一条数据
//获取第一条数据name属性值
return fp.flowRight(fp.prop('name'), fp.first)
}
练习3:
let _average = xs => {
return fp.reduce(fp.add, 0, xs)
}
let averageDollarValue = cars => {
return _average(fp.flowRight(fp.map(fp.prop('dollar_value')))(cars))
}
练习4:
let _underscore = fp.replace(/\s+/g, '_')
let arr = fp.flowRight(fp.map(fp.prop('name')))(cars)
let sanitizeNames = arr => {
return fp.flowRight(fp.map(fp.flowRight(_underscore, fp.toLower)))(arr)
}
三、
//support.js
class Container {
static of(value) {
return new Container(value)
}
construtor(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
}
map (fn) {
return this.isNothing() ? MayBe.of(null) : MayBe.of(fn(this._value))
}
isNothing () {
return this._value === null || this._value === undefined
}
}
module.exports = { MayBe, Container }
练习1:
const fp = require('lodash/fp')
const { MayBe, Container } = require('./support')
let maybe= MayBe.of([5,6,1])
let ex1 = () => {
return maybe.map(arr => fp.flowRight(fp.map(fp.add(1)))(arr))
}
练习2:
let ex2 = () => {
return xs.map(arr => fp.first(arr))
}
练习3:
let ex3 = () => {
return safeProp('name', user).map(x => fp.first(x))
}
练习4:
let ex4 = (n) => {
return MayBe.of(n).map(n => parseInt(n))
}
四、
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class Promise {
constructor(executor) {
//状态初始化为pending
this.status = PENDING
//成功传参
this.value = undefined
//失败原因
this.reason = undefined
//存储成功的回调函数
this.successCallbacks = []
//存储失败的回调函数
this.failCallbacks = []
//成功
let resolve = (value) => {
if(this.status == PENDING) {
this.status = FULFILLED
this.value = value
while (this.successCallbacks.length) this.successCallbacks.shift()()
}
}
//失败
let reject = (reason) =>{
if(this.status == PENDING) {
this.status = REJECTED
this.reason = reason
while (this.failCallbacks.length) this.failCallbacks.shift()()
}
}
try {
executor(resolve, reject)
} catch(err) {
reject(err)
}
}
then(successCallback, failCallback) {
//参数可有可以无
successCallback = successCallback ? successCallback : value => value
failCallback = failCallback ? failCallback : reason => { throw reason}
let promise2 = new Promise((resolve, reject)=>{
if(this.status == FULFILLED) {
setTimeout(()=>{ //异步让promise2先创建
try {
let x = successCallback(this.value)
// 判断 x的值是普通值还是Promise对象
// 普通值 直接调用reslove
// 若是Promise对象,查看Promise对象返回的接口
// 再根据结果,决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject)
} catch(err) {
reject(err)
}
}, 0)
} else if(this.status == REJECTED) {
setTimeout(()=>{ //异步让promise2先创建
try {
let x = failCallback(this.reason)
// 判断 x的值是普通值还是Promise对象
// 普通值 直接调用reslove
// 若是Promise对象,查看Promise对象返回的接口
// 再根据结果,决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject)
} catch(err) {
reject(err)
}
}, 0)
} else {
//存储成功的回调函数
this.successCallbacks.push(()=> {
setTimeout(()=>{ //异步让promise2先创建
try {
let x = successCallback(this.value)
// 判断 x的值是普通值还是Promise对象
// 普通值 直接调用reslove
// 若是Promise对象,查看Promise对象返回的接口
// 再根据结果,决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject)
} catch(err) {
reject(err)
}
}, 0)
})
//存储失败的回调函数
this.failCallbacks.push(()=> {
setTimeout(()=>{ //异步让promise2先创建
try {
let x = failCallback(this.reason)
// 判断 x的值是普通值还是Promise对象
// 普通值 直接调用reslove
// 若是Promise对象,查看Promise对象返回的接口
// 再根据结果,决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject)
} catch(err) {
reject(err)
}
}, 0)
})
}
})
return promise2
}
finally (callback) {
return this.then(value => {
return MyPromise.resolve(callback()).then(() => value);
}, reason => {
return MyPromise.resolve(callback()).then(() => { throw reason })
})
}
catch (failCallback) {
return this.then(undefined, failCallback)
}
static all (array) {
let result = [];
let index = 0;
return new MyPromise((resolve, reject) => {
function addData (key, value) {
result[key] = value;
index++;
if (index === array.length) {
resolve(result);
}
}
for (let i = 0; i < array.length; i++) {
let current = array[i];
if (current instanceof MyPromise) {
// promise 对象
current.then(value => addData(i, value), reason => reject(reason))
}else {
// 普通值
addData(i, array[i]);
}
}
})
}
static resolve (value) {
if (value instanceof MyPromise) return value;
return new MyPromise(resolve => resolve(value));
}
}
function resolvePromise (promise2, x, resolve, reject) {
if(promise2 === x) {
return reject(new TypeError('返回了相同的Promise对象'))
}
if(x instanceof Promise) {
//promise对象
x.then(resolve, reject)
} else {
//普通值
resolve(x)
}
}
module.exports = Promise
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。