簡答題
1、
1.javascript爲何是單線程?javascript
與javascript的設計初衷有關,最先javascript是運行在瀏覽器中的腳本語言,目的是爲了實現頁面上的動態交互,實現頁面的核心是dom操做,因此決定了javascript是單線程,不然會出現線程同步的問題: 好比多個線程同時操做一個dom元素,這時瀏覽器不知道要以誰的操做爲準,形成代碼執行順序混亂 javascript是單線程也就意味着瀏覽器有多個任務的時候要排隊依次進行,一個一個完成,這種模式的優勢是比較安全。缺點是若是咱們遇到一個特別消耗時間的任務,那麼後面的任務就會一直等着這個任務的完成,這樣會形成頁面卡死的狀況,會形成阻塞。 javascript語言沒法處理大量的耗時任務,爲了解決這個問題,javascript講執行任務分紅了兩種模式:同步模式和異步模式
2.同步模式java
同步模式指的是咱們的javascript代碼要依次執行,後面的代碼要等待前一句代碼執行完成才能執行,排隊執行,javascript代碼大多數是以同步模式進行執行的
3.異步模式promise
異步模式指的是咱們的javascript代碼不會等待前面的代碼執行完畢纔開始執行。 咱們將執行的代碼放入到調用棧中執行,若是是同步的直接執行,若是是異步的則放入消息隊列中等待執行,等到全部的代碼執行完畢,咱們的event loop就上場了,它會監聽調用棧和消息隊列中的任務,當調用棧中全部的任務結束之後,它會從消息隊列中依次取出回調函數壓入到調用棧,開始執行,直到整個循環結束
4.Event Loop瀏覽器
主線程從消息隊列中讀取事件,這個過程是循環不斷的,因此整個的這種運行機制稱爲Event Loop(事件循環),Event Loop是javascript的執行機制
5.消息隊列安全
消息隊列是暫時存放異步任務的地方,咱們的異步代碼會存放到消息隊列中,等到同步代碼執行完畢之後,event loop會從消息隊列中依次取出異步任務放到調用棧中再次執行。
6.宏任務,微任務dom
宏任務:當前調用棧中執行的代碼成爲宏任務,包括 主代碼快 ,定時器 微任務:宏任務執行完,在下一個宏任務開始以前須要執行的任務,能夠理解爲回調函數 運行機制: 在執行棧中執行一個宏任務 執行過程當中遇到微任務,將微任務添加到消息隊列中 當前宏任務執行完畢,當即執行微任務隊列中的任務 微任務執行完畢後,把下一個宏任務放到消息隊列中,經過eventloop放到調用棧中執行。
代碼題
1、異步
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 ) })
2、函數
練習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) }
3、oop
//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)) }
4、ui
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