1、同步異步

異步和單線程

  • JS是單線程語⾔,只能同時做⼀件事。
  • 瀏覽器和node.js已⽀持JS啓動進程,如Web Worker。
  • JS和DOM渲染共用同⼀個線程,因為JS可修改DOM結構。

異步是因為單線程而來的。

那麼遇到等待(網絡請求,定時任務)不能卡住,所以需要異步,異步是基於回調callback函數形式。

異步

//異步 
console.log(100); 
setTimeout(()=>{ 
console.log(200)
},1000) //callback 
console.log(300); 
//異步不會阻塞代碼的執⾏。

同步

console.log(100); 
alert(200); 
console.log(300); 
//同步會造成線程的阻塞。

總結

  • JS 是單線程的語⾔
  • 異步不會阻塞代碼的執行
  • 同步會阻塞代碼執行

應用****場景

網絡請求,如何ajax-圖片加載

定時任務,如setTimeout

題目

console.log("start"); 
let img = document.createElement("img"); 
img.onload = function(){ 
console.log("load"); 
} 
img.src= "react.jpg"; 
console.log(img) 
console.log("end")

2、promise

**1-1 promise有幾種狀態 **

pending 
fulfilled 
rejected

pending

var p = new Promise(() => { 

}); 
console.log(p)

fulfilled

var f = new Promise((resolve, reject) => { 
resolve(1) 
}) 
console.log(f)

rejected

var r = new Promise((resolve, reject) => { 
reject(1) 
}) 
console.log(r)

**1-2 狀態之間的切換 **

pending–>fulfilled

var f = new Promise((resolve, reject) => { 
setTimeout(()=>{ 
resolve(1); 
},1000) 
}) 
console.log(f)

pending -->rejected

var r = new Promise((resolve, reject) => { 
setTimeout(()=>{ 
reject(1); 
},1000) 
}) 
console.log(r)

1-3 觸發狀態

**1-3-1 正常觸發 **

1.正常情況下catch和then的返回值都是fulfilled的狀態

2.觸發函數中存在報錯的情況,返回值是rejected的狀態

// then 
var p= new Promise((resolve, reject) => { 
resolve(1); 
reject(2); 
}) 
var r = p.then(res=>{ 
console.log(res) 
}) 
console.log(r) //fulfilled 
//catch 
var p= new Promise((resolve, reject) => { 
reject(2); 
}) 
var c = p.catch(err=>{ 
console.log(err) 
}) 
console.log(c) //fulfilled
//catch 語句報錯 
var p= new Promise((resolve, reject) => { 
reject(2); 
}) 
var r = p.catch(res=>{ 
console.log(res) 
throw "error" 
}) 
console.log(r)

1-3-3 then和catch函數報錯之後的觸發

then和catch報錯之後,獲取的狀態rejected,那麼這種狀態只能使用catch函數去調用

var p= new Promise((resolve, reject) => { 
resolve(1); 
reject(2); 
}) 
var r = p.then(res=>{ 
console.log(res) 
throw "error" 
}) 
var t = r.catch(res=>{ 
console.log(res) 
}) //

1-4 promise實現圖片加載

const url ="react.jpg"; 
function loadImg(src){ 
return new Promise((resolve,reject)=>{ 
const img = document.createElement("img"); img.onload = ()=>{ 
resolve(img); 
} 
img.onerror = ()=>{ 
reject(new Error("圖⽚加載失敗")) 
} 
img.src = src; 
}) 
} 
loadImg(url).then(res=>{ 
console.log(res.width) 
}).catch(err=>{ 
console.log(err) 
})

3、Async,await-catch

```javascript (async()=>{ try{ var res = await jjf; }catch(err){ console.log(err); } })(); ```

Event-Loop

JS是單線程運行的
異步要基於回調來實現
event loop就是異步回調的實現原理

JS如何執行

從前到後,⼀行⼀行執行
如果某⼀行執行報錯,則停止下⾯代碼的執行
先把同步代碼執行完,再執行異步代碼

console.log(“start”); setTimeout(()=>{
console.log(“callback”) },2000)
console.log(“end”);

2022最新Web前端經典面試試題及答案-史上最全前端面試題(含答案)_Vue

編輯

同步代碼執⾏完畢,就會啓動event-loop,是瀏覽器內核啓動的。

4、調用棧

1、console.log("start")執行先將其放在調用棧中,控制枱輸出"start"

2022最新Web前端經典面試試題及答案-史上最全前端面試題(含答案)_#前端_02

編輯

2、console.log(“start”)執行完畢,將其從調用棧中移除

接着將setTimeout()函數到調用棧中,因為它是⼀個webAPI,那麼在webAPI中有⼀個定時器。

2022最新Web前端經典面試試題及答案-史上最全前端面試題(含答案)_#前端_03

編輯

3、調用棧中移除setTimeout(),執行console.log(“end”)

2022最新Web前端經典面試試題及答案-史上最全前端面試題(含答案)_#前端_04

編輯

4、console.log(“end”)執行之後,也從調用棧中移除

2022最新Web前端經典面試試題及答案-史上最全前端面試題(含答案)_#前端_05

編輯

5、同步代碼執行完畢之後,Event Loop會不斷的循環callback Queue,看裏面是否有異步任務

2022最新Web前端經典面試試題及答案-史上最全前端面試題(含答案)_#GIS_06

編輯

6、最後Event Loop會將callback Queue中的代碼放到調用棧⾥去

2022最新Web前端經典面試試題及答案-史上最全前端面試題(含答案)_#前端_07

編輯

7、 callback在調用棧中被執行完畢之後,被從調用棧中移除

2022最新Web前端經典面試試題及答案-史上最全前端面試題(含答案)_#前端_08

編輯

Tips:這地方會等待3s之後,callback函數才會被放到Callback Queue中,被Event Loop捕獲。

總結:

1-1 同步代碼,⼀行⼀行放在call stack執行
1-2 遇到異步,會先"記錄"下,等待時機(定時,網絡請求)
1-3 時機到了,就移動到Callback Queue
1-4 Call Stack為空(即同步代碼執行完)Event–Loop開發工作。

1-5 輪詢查找Callback Queue,如有則移動到Call Stack執行。

1-6 繼續輪詢查詢(永動機⼀樣)

5、Event-Loop和Promise

![]()編輯

2022最新Web前端經典面試試題及答案-史上最全前端面試題(含答案)_#WebGIS_09

編輯

  • 微任務是ES6語法規定的
  • 宏任務是由瀏覽器規定的

總結

  • 宏任務有哪些?微任務有哪些?微任務觸發時機更早
  • 微任務、宏任務和DOM渲染的關係
  • 微任務、宏任務和DOM渲染,在event loop的過程

6、Vue

**Vue2 vs Vue3**

1、Vue3相對於Vue2,最核心的是多了⼀個組合式API。

2022最新Web前端經典面試試題及答案-史上最全前端面試題(含答案)_調用棧_10

編輯

Vue2的缺陷,組件的業務邏輯過於複雜的情況,代碼的邏輯分散到各處,代碼比較混動。

2、多了⼀個新的組件Teleport,Suspense
3、組件中可以定義多個根節點
4、組件中是按需導入的Tree Shaking支持(ES Module)

Vue3不會將所有的API都打包進來,只會打包你用到的API。

5、⽣命週期會有不同

6、計算,監聽,keep-alive語法堂都不⼀樣了

7、定義響應式的方法不同

vue2 和vue 3的生命週期

⽣命周期函數,就是Vue在某⼀點自動執行的函數。

2022最新Web前端經典面試試題及答案-史上最全前端面試題(含答案)_#前端_11

編輯

7、Vue3中的setup語法糖的優勢

Vue3中的setup語法糖是⼀個新特性,它提供了⼀種新的方式來編寫Vue組件。它的優勢主要包 括: 1. 更加簡潔的代碼:使⽤setup語法糖,可以將組件選項分為兩部分,⼀部分是props、data、 computed、watch等選項,另⼀部分是⽣命週期鈎⼦函數。這樣可以使代碼更加簡潔易懂。 2. 更加靈活的組件選項:在setup中可以使用響應式數據、計算屬性、watch等,這樣可以讓組 件選項更加靈活,也可以更好地實現複雜的業務邏輯。 3. 更加清晰的邏輯分離:使用setup語法糖可以更好地將組件的邏輯分離,使得組件的數據和邏 輯更加清晰明瞭,便於維護和開發。 4. 更好的性能:由於Vue3中使用了Proxy來實現響應式數據,setup語法糖可以更好地利用Proxy 的優勢,提⾼組件的性能。 綜上所述,Vue3中的setup語法糖提供了更加簡潔、靈活、清晰和⾼性能的方式來編寫Vue組件, 可以幫助開發者更加⾼效地開發和維護Vue應用。

8、ref vs reactive

僅從代碼層⾯討論 1、ref只可以定義單個響應式數據 2、reactive可以定義多個響應式數據,和Vue2中的data類似

死死記住:ref本質也是 reactive,ref(obj)等價於 reactive({value: obj})

  • vue3中實現響應式數據的方法是就是使用ref和reactive,所謂響應式就是界面和數據同步,能實現實時更新。
  • vue2中響應式是通過defineProperty實現的,vue3中是通過ES6的Proxy來實現的。
<template> 
<div></div> 
</template> 
<script setup > 
import { ref, isRef, reactive } from "vue"; 
const count = ref(10); 
const state = reactive({ 
value: 20, 
}); 
console.log(count.value); 
console.log(isRef(count)); 
console.log(state.value) 
</script> 
<style scoped> 
</style>

2022最新Web前端經典面試試題及答案-史上最全前端面試題(含答案)_#前端_12

編輯

2022最新Web前端經典面試試題及答案-史上最全前端面試題(含答案)_調用棧_13

編輯

**9、vue3如何設置全局變量**

注意,使用全局變量是有⼀定的⻛險的,因為它們可能被不同的組件或庫使用,並且可能會被不小 心覆蓋或修改。因此,應該謹慎使用全局變量,最好將它們限制在必要的範圍內。

1、app.config.globalProperties
要設置Vue 3全局變量,可以使用Vue 3提供的createApp方法

1、main.js

import { createApp } from 'vue' 
import App from './App.vue' 
const app = createApp(App); 
app.config.globalProperties.$http = 'Hello, world!' 
app.mount('#app')

2、組件中使用

<template>App</template> 
<script setup> 
import { getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance(); 
console.log(proxy.$http) 
</script>

2、provide - inject

main.js

const app = createApp(App); 
app.provide("$http","http") 
app.mount('#app') 
<template> 
<div>App</div> 
</template> 
<script setup> 
import { inject } from 'vue'; 
const http = inject("$http"); 
console.log(http) 
</script>

3、Vue和ol

1、設置原型

/* 定義原型 */ 
export const prototype = app.config.globalProperties;

2、在組件中設置原型屬性的值

<template> 
<div id="map"></div> 
</template> 
<script setup> 
import { onMounted } from "vue"; 
import { gaode } from "../map_libs/gaode"; import { prototype } from "../main"; //重要 onMounted(() => { 
/* Pinia  全局對象 */ 
const map = new ol.Map({ 
target: "map", 
layers: [gaode], 
view: new ol.View({ 
projection: "EPSG:4326", 
center: [114.3, 30.5], 
zoom: 4, 
}), 
}); 
prototype.$map = map; //重要 
}); 
</script>

3、封裝獲取全局屬性的工具函數

可以幫助我們更好的獲取Map,這個函數建議放置自動導包中

/* 推薦放到⾃動導包中 */ 
import { getCurrentInstance } from 'vue' 
function useGlobalMap() { 
const { proxy } = getCurrentInstance(); 
/* getCurrentInstance().appContext.config.globalProperties.$map */ return (proxy.$map); 
} 
export { useGlobalMap };

4、組件中使用全局Map

<template>control</template> 
<script setup> 
import {  onMounted } from "vue"; 
import { useGlobalMap } from "../utils/globalMap"; onMounted(() => { 
console.log(useGlobalMap()); 
}); 
</script>

10、Vuex和Pinia有什麼區別,那個更好用?

Vuex 和Pinia 都是用於Vue.js 應用程序狀態管理的庫,它們的主要目的是將應用程序狀態集中管 理,使得應用程序的狀態變得可預測和可維護。然而,它們在實現上存在⼀些不同。 以下是Vuex 和Pinia 的⼀些區別: 1. Vuex 是Vue.js 官方提供的狀態管理庫,而Pinia 是社區驅動的狀態管理庫。 2. Vuex 使用單⼀的全局狀態樹來管理整個應用程序的狀態,而Pinia 使用多個獨立的狀態存儲 來管理狀態,每個存儲都可以包含自己的狀態、getter、mutation 和action。 3. 在Vuex 中,所有的狀態、mutation 和action 都是全局的,任何組件都可以直接訪問它們。 而在Pinia 中,狀態存儲只能通過組件實例來訪問和修改,這使得狀態變得更加可控和預測。 4. 在使用Vuex 時,需要先創建⼀個store,然後將它注入到根 Vue 實例中。而在使用Pinia 時,不需要創建⼀個全局的store,而是可以在組件內部直接使用狀態存儲。 5. Pinia 支持TypeScript,它提供了更好的類型支持和自動化類型推斷。 總之,Vuex 和Pinia都是⾮常優秀的狀態管理庫,具體選擇哪⼀個取決於項目的需求和開發者的 個⼈喜好。

1、Vuex

2022最新Web前端經典面試試題及答案-史上最全前端面試題(含答案)_#WebGIS_14

編輯

**2、Pinia **

核心概念

1、State
2、Getter
3、Action

代碼實現:

import { ref, computed } from 'vue' 
import { defineStore } from 'pinia' 
export const useCounterStore = defineStore('counter', () => { const count = ref(0) 
const doubleCount = computed(() => count.value * 2) function increment() { 
count.value++ 
} 
return { count, doubleCount, increment } 
})