[toc]
#### 1.js數據類型,區別
1.基本數據類型
+ string
+ number
+ null
+ undefined
+ boolean
+ Symbol
```javascript
唯一數
let sym = Symbol('描述')
```
+ BigInt 大整數
```js
js最大支持53位數,為了表示最大精度以外的數,新增了BigInt類型
let num = 123n
typeof num // bigint
可以進行加減乘除
如果除法有小數,會被舍棄小數部分
```
2.引用數據類型
+ Object
+ Function
+ Array
#### 2.Object.assign(target, source)
將后面的對象key以及內容覆蓋到target對象上
#### 3.constructor
#### 4.手寫map
```js
Array.prototype._map = function(callback) {
let res = []
for (let i=0; i<this.length; i++) {
res.push(callback(this[i], i, this))
}
return res
}
```
#### 5. for of 能遍歷對象嗎?
不能,只能遍歷可迭代的對象,如 Array, Map, Set 等
#### 6.instanceOf 作用,手寫一個
instanceOf 主要用于判斷一個實例是否屬于某種類型
`left instanceOf rightClass`,右邊的prototype在左邊的原型鏈上即可
```js
function instance_of(l, r) {
let o = r.prototype // 獲取 r 的原型
let pL = l.__proto__ // 獲取 l 的原型
// 尋找 l 的原型鏈,看是否存在 o,直到原型指向 null
while(true) {
if (pL === null) {
return false
}
if (o === pL) { // 找到 l 的原型鏈上存在 等于 l
return true
}
pL = pL.__proto__
}
}
```
#### 7.數組去重
1. new Set(arr) 方法
2. 遍歷法,includes判斷
3. Map方法,把值存在 Map對象的 key上,遍歷arr,判斷Map是否存在該item,如果不存在則push到新數組
```js
// set
function uni(arr) {
return [...new Set(arr)]
}
// Map 遍歷法
function uni2(arr) {
let map = new Map()
let res = []
arr.forEach(item => {
if (!map.has(item)) {
map.set(item, true)
res.push(item)
}
})
return res
}
// 雙指針修改原數組
function uni3(arr) {
let i = 0, // 非重復位置
j = 0; // 指針
// 指針j開始移動
for (0; j<arr.length; j++) {
// 如果j和i項不一樣,則i+1,將j的值賦給i, j繼續+1
// 如果一樣,i不動,j++
// 所以 i的位置就是非重復數組的最后一個位置
if (arr[i] !== arr[j]) {
i++
arr[i] = arr[j]
}
}
return arr.slice(0, i+1)
}
let arr = [1, 1, 2, 2, 3, 3]
console.log(uni(arr));
console.log(uni2(arr));
console.log(uni3(arr));
```
#### 8.類數組與數組區別,轉換
1.類數組
+ 通過class類名,或者標簽名獲取dom,得到的就是類數組
+ 函數內arguments代替參數
+ 手動實現
```js
let al1 = {
length: 5,
0: 0,
1: 1,
3: 3,
4: 4,
5: 5,
};
```
2.類數組轉化為數組
+ Array.from
+ Array.prototype.slice.call(objArr)
```js
console.log(Array.from(objArr));
console.log(Array.prototype.slice.call(objArr));
```
#### 9.手寫發布訂閱
原理:創建一個發布訂閱 class,用event對象{}存儲事件名,以及回調函數
on,訂閱,指的是創建事件名對應的回調函數,或者往callbacks數組中push方法
off,解除訂閱,指的是callbacks數組中刪除某個方法,或者清空
emit, 觸發訂閱事件,指的是遍歷執行callbacks數組中的方法,但是注意args傳參,以及this指向
```js
class EventPubSub {
constructor() {
this.event = {} // 事件集合
}
// 訂閱
// type: 事件名, callback: 回調函數
on(type, callback) {
// 如果訂閱的事件不存在
if(!this.event[type]) {
this.event[type] = [callback] // 發布訂閱需要執行的callback是一個callback數組
} else {
this.event[type].push(callback)
}
}
// 解除訂閱,解除的是callback一樣的某一個
off(type, callback) {
if(!this.event[type]) {
return
}
if (callback) {
this.event[type] = this.event[type].filter(item => {
return item !== callback
})
} else {
this.event[type] = []
}
}
// 發布,執行
emit(type, ...args) {
if (!this.event[type]) {
return
}
this.event[type].forEach(callback => {
callback.apply(this, args)
})
}
}
let event = new EventPubSub
event.on('click', (args) => {
console.log('觸發click方法', args);
})
event.emit('click', 1)
```
#### 10.手寫數組轉成樹
```js
// 例如將 input 轉成output的形式
let input = [
{
id: 1, val: '學校', parentId: null
}, {
id: 2, val: '班級1', parentId: 1
}, {
id: 3, val: '班級2', parentId: 1
}, {
id: 4, val: '學生1', parentId: 2
}, {
id: 5, val: '學生2', parentId: 2
}, {
id: 6, val: '學生3', parentId: 3
},
]
let output = {
id: 1,
val: '學校',
children: [{
id: 2,
val: '班級1',
children: [
{
id: 4,
val: '學生1',
children: []
},
{
id: 5,
val: '學生2',
children: []
}
]
}, {
id: 3,
val: '班級2',
children: [{
id: 6,
val: '學生3',
children: []
}]
}]
}
```
```js
function arrToTree(arr) {
// 1.先定義 id 的 hashMap, id -> item
// 2.再遍歷 arr,通過 parentId判斷將當前 item 掛到 hashMap下哪一個item的children中
let idMap = {}
arr.forEach(item => {
idMap[item.id] = item
})
arr.forEach(item => {
if (idMap[item.parentId]) {
let parentItem = idMap[item.parentId]
if (parentItem.children && parentItem.children.length >= 0) {
parentItem.children.push(item)
} else {
parentItem.children = [item]
}
}
})
// 3.獲取樹的最外層,即沒有parentId的那層
return arr.filter(item => !item.parentId)
}
```
#### 11.Set, Map, WeakSet和WeakMap區別
+ Set
```js
1.可以遍歷, forEach
2.類似不能重復的數組 new Set([1, 2, 3])
3.add, delete, has
```
+ WeakSet
```js
1.不可以遍歷
2.成員都是對象,引用類型
3.不能遍歷,add, delete, has,沒有size
```
+ Map
```js
1.可以遍歷,forEach((value, key))
2.類似對象,但是key可以是多種類型
3.set, delete, has, clear, size
```
+ WeakMap
```js
弱引用類型
1.不可以遍歷,沒有size, values, keys等,key必須為對象,目的是為了不會被垃圾回收考慮,當WeakMap沒有被使用時會自動銷毀
2.set, delete
```
#### 12.js存在哪幾種內存泄露的情況
1. 意外的全局變量
2. 閉包
3. 未被清空的定時器
4. 未被銷毀的事件監聽
5. DOM引用
#### 13.js判斷數組
```js
1.Array.isArray(arr) // true
2.arr instanceof Array // true
3.arr.constructor === Array // true
4.Object.prototype.toString.call(arr) === '[Object Array]'
```
- JavaScript
- 1. DOM事件流
- 2. 模擬 new, Object create(), bind
- 5. 封裝函數進行字符串駝峰命名的轉換
- 6. 什么是promise
- 7. 判斷一個數是否為數組
- 10. __proto__和prototype以及原型,原型鏈,構造函數
- 11. 繼承
- 12. 閉包
- 13. 回調函數
- 14. var 和 let 區別
- 15. this、bind、call、apply
- 16.undefined和null的區別
- 17.內存泄漏
- 18.垃圾回收機制
- html css
- 1. 元素垂直水平居中
- 2. 清除浮動
- 3. bootstrap柵格系統
- 4. px rpx em rem vw 的區別
- 5. 兩種盒子模型
- 6. 合集
- web類
- 1. html5的新特性以及理解(web標簽語義化)
- 2. 什么是路由,關于前端路由和后端路由
- 3. 對優質代碼的理解
- 4. cookie 和 sessionStorage和localStorage
- 5. 瀏覽器內核
- 6. http 狀態碼
- 7. href 和 src 的區別
- 8. link 和 @import 的區別
- 9. http 狀態碼
- 10. websocket
- 11. 瀏覽器解析url
- 12.http緩存
- vue
- 1.vue2和vue3有哪些區別
- 1. 對 mvvvm 的理解
- 2. mvvm的優缺點
- 3. 數據雙向綁定的原理
- 4. 生命周期
- 5. 組件如何通信
- 6. computed和watch的區別
- 7. proxy 和 Object.defineProperty
- 8. 虛擬dom和 diff算法
- 9. 路由的嵌套與傳參
- 10. 路由導航鉤子
- 11. axios 的理解
- 12. vue自定義指令 diretive
- 13. diff 的實現
- 14. 實現一個簡單的雙向綁定
- 15. 為什么 data 是一個函數
- 題譜
- js
- 手寫篇
- css
- vue
- react
- 算法
- 自我介紹
- 八股文
- 源項目地址
- 1.計算機網絡
- 2.瀏覽器
- 3.html和css
- 4.javascript
- 6.typescript
- 7.vue
- 8.react
- 大廠面試
- 面試題大全
- 常見性能優化
- 面試實戰
- 面試分析
- 押題
- 1.微前端在項目中的實際應用
- 2.性能優化
- vue相關
- 1.說一說HashRouter和HistoryRouter的區別和原理
- 無敵之路,牛客網面試題自測記錄
- 前端基礎
- 1.html
- 2.js基礎
- 珠峰性能優化
- WebWorker
- url到渲染
- 瀏覽器加載機制
- 自我介紹1
- 手寫題
- 1.compose
- 2.setTimeout模擬setInterval
- 3.手寫數組拍平
- 4.手寫promise.all
- 5.手寫深拷貝
- webpack
- 實戰