JS 學習總結
1. typeof能判斷的類型?(JS變量類型)
答:undefined、number、string、boolean、symbol、object、function
2. 何時使用===,何時使用==(強制類型轉換)
答:任何時候都用===,除非是判斷==null
3. window.onload和DOMContentLoaded的區別(頁面加載過程)
答:window.onload是在頁面元素全部加載結束後觸發,二DOMContentLoaded是在頁面的骨架渲染出來,而圖片等資源尚未渲染時觸發,用戶等待時間短
4. JS創建10個<a>
標籤,點擊彈出對應的序號(JS作用域)
答:
for(let i = 0; i < 10; i++){
const a = document.createElement('a');
a.href="javascript:;";
a.addEventListener('click', function () {
alert(i)
})
a.innerHTML = `標籤${i}`;
document.body.appendChild(a)
}
5. 手寫節流throttle和防抖debounce(性能、體驗優化)
- 防抖debounce
function debounce (fn ,delay = 500) {
let timer = null
return function () {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout( () => {
fn.apply(this, arguments)
}, delay)
}
}
const input = document.getElementById('input')input.addEventListener('keyup', debounce(function(){
console.log(this.value)
}, 1000))
- 節流throttle
function throttle(fn, delay = 100) {
let timer = null
return function () {
if (timer) {
return
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay);
}
}
const div = document.getElementById('div')
div.addEventListener('drag', throttle(function(e){
console.log(e.offsetX, e.offsetY)
}, 200))
6. Promise解決什麼問題?(JS異步)
答:回調地獄
7. 值類型和引用類型的區別(值類型和引用類型)
答:值類型是存放在棧中。引用類型是放在堆中,棧中存放的是該變量在堆中的內存地址。
8. 手寫深拷貝 (值類型和引用類型)
/**
* 深拷貝
* @param {Object} obj 要拷貝的對象
*/
function deepClone(obj) {
if (typeof obj !== 'object' || obj === null) return obj
let newObj
if (obj instanceof Array) {
newObj = []
} else {
newObj = {}
}
for (let key in obj) {
if (obj.hasOwnProperty(key))
newObj[key] = deepClone(obj[key])
}
return newObj
}
9. 如何準確判斷一個變量是不是數組?(原型鏈)
答:a instanceof Array
10. 手寫一個簡易的jQuery, 考慮插件和擴展性 (class)
答:
class jQuery {
constructor(selector) {
this.selector = selector
const res = document.querySelectorAll(selector)
for(let i = 0; i < res.length; i++) {
this[i] = res[i]
}
this.length = res.length
}
get (index) {
return this[index]
}
each (fn) {
for(let i = 0; i < this.length; i++) {
fn(this[i])
}
}
on (type, fn) {
return this.each(function (ele) {
ele.addEventListener(type, fn, false)
})
}
}
const p = new jQuery('p')
console.log(p.get(0))
// 插件
jQuery.prototype.dialog = function (info) {
alert(info)
}
// 造輪子
class myJQuery extends jQuery {
constructor(selector) {
super(selector)
}
// 擴展自己的方法
addClass(className) {
}
style(data) {
}
}
11. class的原型本質,怎麼理解?(原型和原型鏈)
答:所有的實例都有隱式原型__proto__
,所有的class都有顯示原型prototype
,實例的隱式原型__proto__
強等於class的顯示原型 prototype
,而class的顯示原型prototype的隱式原型__proto__
等於父類的顯示原型prototype
12. this的不同應用場景,如何取值?(作用域)
- 作爲普通函數this指向window
- 使用call、apply、bind,傳入什麼this就指向什麼
- 作爲對象方法被調用,指向調用它的對象
- 在class方法被調用,指向調用它的對象
- 箭頭函數,不改變this指向,this是上級作用域的this
13. 手寫bind函數(this)
答:
const obj = {
name: 'yibo'
}
function fn(a, b) {
console.log(this)
console.log(a + b)
return a + b
}
function myBind(obj) {
const context = this
const newArguments = Array.prototype.slice.call(arguments)
newArguments.shift()
return function () {
return context.apply(obj, newArguments)
}
}
const res = fn(1, 2)
console.log(res)
Function.prototype.myBind = myBind
const myFn = fn.myBind(obj, 5, 8)
const res2 = myFn()
console.log(res2)
14. 實際開發中閉包的應用場景,舉例說明
答:
// 閉包隱藏數據,只提供API
function createCache () {
// 閉包中的數據,被隱藏,不被外接訪問
const data = {}
return {
set: function (key, val) {
data[key] = val
},
get: function (key) {
return data[key]
}
}
}
const c = createCache()
c.set('a', 100)
console.log(c.get('a'))
15. 同步和異步的區別是什麼?(JS異步和單線程)
答:同步會阻塞代碼執行,異步不會阻塞代碼執行
16. 手寫用Promise加載一張圖片(Promise)
答:
const url = 'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg'
function loadImg(src) {
return new Promise((resolve, reject) => {
console.log('start')
const img = document.createElement('img')
img.onload = () => {
console.log('loaded')
resolve(img)
}
img.onerror = () => {
resolve(new Error(`圖片加載失敗${src}`))
}
img.src = src
console.log('end')
})
}
loadImg(url)
.then(img => {
document.body.appendChild(img)
return img
})
.then(img => {
console.log(img.height)
})
.catch(err => console.log(err))
17. 前端使用異步的場景有哪些?
答:網絡請求、圖片加載、定時任務
18. DOM是哪種數據結構?
答:樹形結構
19. DOM操作的常用API
增刪改查:getElementsByTagName、getAttribute、setAttribute、createElement、appendChild、removeChild
20. attribute和property的區別
property: 修改對象屬性,不會體現到HTML結構中
attribute:修改HTML屬性,會改變HTML結構
兩者都可能引起DOM重新渲染
21. 一次性插入多個DOM節點,考慮性能
答:
const list = document.getElementById('list')
// 創建一個文檔片段
const fragment = document.createDocumentFragment()
for(let i = 0; i < 10; i++){
const li = document.createElement('li')
li.innerHTML = i
// 插入到文檔片段,文檔片段是在內存中
fragment.appendChild(li)
}
// 將文檔片段一次性插入
list.appendChild(fragment)
22. 如何識別瀏覽器的類型
答:UA,navigator.userAgent
23. 分析拆解URL各個部分
答:${protocol}${host}${pathname}${search}${hash} === ${href}
24. 編寫一個通用的事件監聽函數
答:
function bindEvent(ele, type, selector, fn) {
if(!fn) {
fn = selector
selector = null
}
ele.addEventListener(type, function(event){
const target = event.target
if(selector){
if(target.matches(selector)){
fn.call(target, event)
}
}
else {
fn.call(target, event)
}
})
}
25. 描述事件冒泡的流程
答:基於DOM屬性結構,事件會順着觸發元素往上冒泡,應用場景:代理
26. 無限下拉的圖片列表,如何監聽每個圖片的點擊?
答:事件代理,用e.target獲取觸發元素,用matches來判斷是否是觸發元素
27. 手寫一個簡易的ajax
答:
function ajax(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('GET', url, true)
xhr.onreadystatechange = function () {
if(xhr.readyState === 4) {
if(xhr.status === 200) {
resolve(JSON.parse(xhr.responseText))
}else if(xhr.status === 404){
reject(new Error('404 not found'))
}
}
}
xhr.send()
})
}
const url = '/data/test.json'
ajax(url)
.then(res=>console.log(res))
.catch(err=>console.log(err))
28. 描述cookie、localStorage、sessionStorage 的區別
答:容量、API易用性、是否跟隨http請求發送出去
cookie
本身用於瀏覽器和server通訊
被”借用“到本地存儲來
可用window.cookie=’‘來修改
缺點
存儲大小:最大4kb
http請求時需要發送到服務端,增加請求數據量
只能用document.cookie=’'來修改,太過簡陋
localStorage、sessionStorage
HTML5專門爲存儲而設計,最大可存5M
API簡單易用,setItem、getItem
不會隨http請求發送到服務器端
localStorage數據會永久存儲,除非代碼或手動刪除
sessionStorage數據只存在於當前會話,瀏覽器關閉則清空
一般用localStorage更多一些
29. 從輸入url到渲染出頁面的整個過程
答:下載資源:各種資源類型,下載過程。渲染頁面:結合HTML、CSS、JavaScript、圖片等
30. window.onload和DOMContent的區別
答:
window.addEventListener('load', funciton () {
// 頁面的全部資源加載完纔會執行,包括圖片、視頻等
})
document.addEventListener('DOMContentLoaded', function () {
// DOM 渲染完即可執行,此時圖片、視頻可能還沒加載完
})
31. 爲何建議把CSS放在head中?
答:讓DOM在生成之前就和CSS整合,然後一次性渲染完。
32. 爲何建議把JS放在body之後?
答:頁面渲染過程比較長,被js阻礙
33. 常見的web前端攻擊方式有哪些?
答:XSS跨站請求攻擊:替換特殊字符 <、 >、