① for...in for...of(es6引入)
-
for...in循環(huán)遍歷key -
for...of循環(huán)遍歷item,對象默認(rèn)無法使用,因為沒有部署Iterator遍歷器接口。如果和Object.keys()搭配使用,即使不部署iterator接口也可以遍歷。
② async await理解
- 引入
promise,是異步編程的一種方式,解決了ES6之前的回調(diào)地獄的問題。 -
async返回的是一個promise對象。 -
async函數(shù)中可以不包含await, 但是await必須在async函數(shù)中,await后面的表達(dá)式可以是promise,也可以是非promise,如果是promise,則返回值就是promise的resolve()的值,如果promise是rejecte(),那么需要使用try catch來捕獲異常,如果是非promise值,返回值就是表達(dá)式的返回值。 -
async和await算是promise的語法糖,真正實現(xiàn)了沒有回調(diào)函數(shù)獲取到值。ps :then()也算是回調(diào)函數(shù)。
③ v-model 雙向綁定原理
- 本質(zhì)上是
v-bind和v-on的結(jié)合體 - 通過訂閱發(fā)布結(jié)合
Object.defineProperty()實現(xiàn)雙向綁定。-
Object.defineProperty()劫持了屬性的get,set方法,一旦數(shù)據(jù)發(fā)生改變,則會通知訂閱者發(fā)布更新(update),從而更新視圖。
-
④ vue的通信方式
④ - ① 組件間通信的方式
- 父子組件通信
-
props(父 -> 子)$emit(子 -> 父) -
$parent$children, 訪問父組件實例,或子組件實例 -
provide/ inject, 是vue2.2.0新增的api,父組件中配置了provide,子組件配置inject注入即可。(示例代碼如下:C 是 B 的子組件,B 是 A 的子組件)
-
// A.vue
<template>
<div>
<comB></comB>
</div>
</template>
<script>
import comB from '../components/test/comB.vue'
export default {
name: "A",
provide: {
for: "demo"
},
components:{
comB
}
}
</script>
// B.vue
<template>
<div>
{{demo}}
<comC></comC>
</div>
</template>
<script>
import comC from '../components/test/comC.vue'
export default {
name: "B",
inject: ['for'],
data() {
return {
demo: this.for
}
},
components: {
comC
}
}
</script>
// C.vue
<template>
<div>
{{demo}}
</div>
</template>
<script>
export default {
name: "C",
inject: ['for'],
data() {
return {
demo: this.for
}
}
}
</script>
-
ref refs- 如果在普通的DOM元素上使用,則引用是DOM元素,如果是子組件使用,引用則是子組件的實例,可以通過實例直接調(diào)用組件方法或者訪問組件數(shù)據(jù)。
-
EventBus不推薦使用,當(dāng)項目過大時,難以維護(hù) - VueX
- localStorage / sessionStorage
④ - ② 路由間傳參
⑤ vue計算屬性緩存原理?
⑥ 深拷貝淺拷貝
- 深淺拷貝一般發(fā)生在引用類型上面,普通數(shù)據(jù)類型永遠(yuǎn)都是深拷貝。當(dāng)拷貝引用類型時,拷貝的僅僅是引用,內(nèi)存中的地址值還是相同的。即改變拷貝后的數(shù)據(jù),會對原數(shù)據(jù)發(fā)生影響。
- 修改副本數(shù)據(jù)影響原數(shù)據(jù)的是淺拷貝,不影響源數(shù)據(jù)的是深拷貝。
- 深拷貝的實現(xiàn):
-
lodash函數(shù)庫 - 遞歸實現(xiàn)、
-
JSON.parse(JSON.stringify())、如果對象中有function,undefined,regExp則會忽略 -
concat和slice也可以實現(xiàn)(僅對基本類型的數(shù)據(jù)生效)
-
⑦ 介紹一下http,https,為什么https比http更安全?
- http:超文本傳輸協(xié)議,以明文的形式傳輸內(nèi)容,不提供任何加密。攻擊者一旦獲取到傳輸報文,就可以讀取到報文信息
- https:安全套接字層超文本傳輸協(xié)議,在http的基礎(chǔ)上添加了SSL協(xié)議,SSL依靠證書來驗證服務(wù)器的身份,并未瀏覽器和服務(wù)器之間的通信加密。
https的原理
- 發(fā)送HTTPS請求,連接到server的433端口
- 在服務(wù)端配置數(shù)字證書
- 傳送證書
- 客戶端解析并驗證證書的有效性
- 加密信息(用的是證書加密后的隨機(jī)值,客戶端和服務(wù)端的通信就可以進(jìn)行加密了)
- 服務(wù)端解析加密信息
- 傳輸加密信息
- 客戶端接收信息
https的優(yōu)缺點
- 優(yōu)點:安全,SEO(搜索排名靠前)
- 缺點:費用,SEO(頁面加載變慢,功耗增大,并非絕對安全)
⑧ forEach 和 map 的區(qū)別
-
forEch沒返回值,或者說返回值是undefined,直接在函數(shù)內(nèi)操作循環(huán)項目。會改變原數(shù)組。 -
map返回一個操作后的數(shù)組,不會改變原數(shù)組。一般在函數(shù)內(nèi)return
⑨ 垂直居中方式
- 定位
- flex布局
- grid布局
- vertical-align:middel (圖片垂直居中)
- line-height: (文字圖片垂直居中)
⑩ Tcp三次握手,四次揮手原理
? 輸出url到頁面完成的整個過程?
- 查找緩存,看是否有緩存好的資源可以提高加載速度。
- DNS解析,將域名解析成IP地址。
- TCP三次握手(雙方發(fā)包的過程)
- 發(fā)送HTTP請求
- 服務(wù)端處理HTTP請求,并返回響應(yīng)報文
- 瀏覽器接受響應(yīng)報文并解析,并且渲染
- 斷開連接(TCP四次揮手)
關(guān)于第六步:
如果返回的是HTML頁面,瀏覽器會將html解析成dom樹,css解析成css規(guī)則樹,結(jié)合dom樹和規(guī)則樹形成渲染樹。根據(jù)渲染樹中的每一個DOM節(jié)點計算出相應(yīng)的位置后開始渲染。
? 排序算法,冒泡排序?
- Array.prototype.sort(),使用的是快速排序。
冒泡排序(思路如下)
- 數(shù)組中有
n個數(shù),比較相鄰的的兩個數(shù),如果前者大于后者,就把兩個數(shù)字交換位置。這樣一來,第一輪就可以選出一個最大的數(shù)放在最后面;那么經(jīng)過(n-1)輪,就完成了所有數(shù)的排序。
冒泡排序
// 冒泡排序?qū)懛?const arr = [1, 20, 10, 30, 22, 11, 55, 24, 31, 88, 12, 100, 50];
function swap(arr, i, j){
const temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
for(let i = 0; i < arr.length - 1; i++){
let flag = false;
for(let j = 0; j < arr.length - 1 - i; j++){
if(arr[j] > arr[j+1]){
swap(arr, j, j+1);
flag = true;
}
}
if(!flag){
break;
}
}
? web安全性?
- xss攻擊 :兩大要素:攻擊者提交惡意代碼,瀏覽器執(zhí)行惡意代碼。解決方案:防止用戶注入惡意代碼。
- csrf攻擊 : 使用cookie冒充用戶發(fā)送請求,導(dǎo)致目標(biāo)網(wǎng)站錯誤響應(yīng)
- dns劫持 : dns涉嫌違法,較少
- http劫持 : 使用https
? 變量提升?
- var會變量提升
- function 聲明也會函數(shù)提升
? Node.js理解?文件讀寫?
- 理解 : 既是開發(fā)平臺,也是運行環(huán)境。基于v8引擎開發(fā)的,所以編程時使用javascript,可以理解為 讓js在服務(wù)器上運行的平臺。
- 文件讀寫: 引入
require('fs')模塊,fs.writeFile() 、 fs.readFile()
? 手寫Map方法
- 第一個參數(shù)是函數(shù),第二個參數(shù)可指定函數(shù)中的this
Array.prototype._map = function(fn,thisValue){
// 賦值數(shù)組給arr
let arr = thisValue || this
// 聲明一個空數(shù)組,作為將要返回的結(jié)果
let result = []
// 判斷第一個參數(shù)是否為函數(shù)
if(typeof fn !== 'function'){
throw new Error(fn + '該參數(shù)必須要為函數(shù)')
}
// 進(jìn)行循環(huán)并且將執(zhí)行結(jié)果返回
for (let i = 0; i < arr.length ; i ++){
let r = fn.call(arr , arr[i] , i , arr)
result.push(r)
}
return result
}
let myMapVal = [1,2,8,6]._map((item)=>{
return item * 2
})
console.log(myMapVal) // [2, 4, 16, 12]
? 箭頭函數(shù)與普通函數(shù)的區(qū)別?
- 箭頭函數(shù)寫法更為簡潔
- 箭頭函數(shù)內(nèi)部沒有
this,箭頭函數(shù)中的this執(zhí)行編寫時的環(huán)境。 -
call、apply、bind無法改變this的指向 - 箭頭函數(shù)繼承而來的
this,指向永遠(yuǎn)不會改變 - 構(gòu)造函數(shù)不能使用箭頭函數(shù)
- 箭頭函數(shù)沒有自己的
arguments - 箭頭函數(shù)沒有原型
prototype - 箭頭函數(shù)不能用作
Generator函數(shù),不能使用yeild關(guān)鍵字
? 何時用Object,何時用Map
- 當(dāng)我們只需要用到一個簡單,便于操作的鍵值對數(shù)據(jù)結(jié)構(gòu)時,用Map更具有優(yōu)勢。因為Map具有各種操作數(shù)據(jù)的方法,
get set has delete等。但是Object始終是基石,因為JSON是直接支持轉(zhuǎn)換為Object的,JSON暫未支持Map結(jié)構(gòu)。
? 原型鏈理解
- 當(dāng)訪問實例對象的屬性或者方法時,首先會在自身查找看是否有定義,如果沒有就去
__proto__屬性查找,一直到原型鏈的頂端(null),因為Object.proto為null,如果還沒有則報錯(屬性是輸出undefined,函數(shù)是xxx is not a function)。 - 首先說原型 、 再說原型與實例的關(guān)系。
? new 關(guān)鍵字背后所做的事情
-
new執(zhí)行的構(gòu)造函數(shù),函數(shù)內(nèi)部默認(rèn)生成了一個對象。 - 函數(shù)內(nèi)部的
this,指向新生成的對象。 -
new執(zhí)行后生成的對象,默認(rèn)是該構(gòu)造函數(shù)的返回值。
? 介紹一下 Set 和 Map 結(jié)構(gòu)
Set
- 類似于數(shù)組,只不過該結(jié)構(gòu)內(nèi)的成員是不重復(fù)的。比數(shù)組豐富的操作方法,如
add,delete,has,clear, 屬性:size - 遍歷方法(注意:set結(jié)構(gòu)沒有key,或者說key和value是同一個值)
- Set.prototype.keys() 遍歷鍵名
- Set.prototype.values() 遍歷鍵值
- Set.prototype.entries() 遍歷鍵值對
- Set.prototype.forEach(()=>{}) 使用回調(diào)函數(shù)的方法遍歷
weakSet
- 使用
new weakSet(), 參數(shù)只能是數(shù)組,數(shù)組中成員必須是對象。
Map
- 類似于對象,有比對象豐富的操作方法,如
add,get,set,delete,has,屬性:size - 遍歷方法
- Set.prototype.keys() 遍歷鍵名
- Set.prototype.values() 遍歷鍵值
- Set.prototype.entries() 遍歷鍵值對
- Set.prototype.forEach(()=>{}) 使用回調(diào)函數(shù)的方法遍歷
???????????????????????????????