您好,登錄后才能下訂單哦!
本篇內容介紹了“web前端高頻面試題實例代碼分析”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
我:呃~,我們知道this中有個準則就是誰調用就指向誰,這句話潛移默化的會導致我們出現一些誤區,現將可能會出錯的情況總結如下,并付出代碼:
1)我們要知道在全局的時候去得到這個this的話,this都會指向windows,因為我們在全局的情況下使用的東西都會被掛載到window上。
<script>
console.log(this) // 指向window
function a(){
console.log(this)
}
a() // 相當于 window.a(),指向的依舊是 window
</script>
2)我要知道this的指向是會指向上一個調用者的,代碼如下:
看完了代碼,我們知道雖然本質上是由于a才調用了d函數,但是中間還是有一層是c調用了d函數,所以this指向上一級會有一個就近原則的,這點很重要!!!
<script>
var a = {
b:10,
c:{
b:12,
d:function(){
console.log(this)
}
}
}
a.c.d() // {b: 12, d: ?}
</script>
3)我們要知道箭頭函數是沒有作用域的,也就是說是沒有自己的this,它的this永遠向的是上一級的this,下面給出一道某大廠的面試題,大家可以猜一下最后的打印結果是什么?
假設你已經仔細的看完了這道面試題,相信你心中已經有了答案是66了,為什么呢?,要知道箭頭函數是沒有自己的this的,所以需要其去上一級去尋找this,而上一級處于全局作用域,所以打印的便是全局已經掛載的id數66。
<script>
var id = 66
function a(){
setTimeout(()=>{
console.log(this.id)
},500)
}
a({id:22}) // 猜猜結果是什么?
</script>
那我們如何改變this的指向,去控制this指向我們想要的結果呢?給出如下三種方法:
<script>
var id = 66
function a(){
setTimeout(()=>{
console.log(this.id || this)
},500)
}
// call => {} 改變之后并執行一次
a.call({id:22}) // 打印22
// apply => [] 改變之后并執行一次
a.apply([12]) // 打印 [12]
// bind() 不調用,只改變this指向
a.bind(a(id=32)) // 32
</script>
我:呃~,好的,總結如下:
call apply bind三個方法都可以用來改變函數的this指向,具體區別如下:
1)fn.call (newThis,params) call函數的第一個參數是this的新指向,后面依次傳入函數fn要用到的參數。會立即執行fn函數。
2)fn.apply (newThis,paramsArr) apply函數的第一個參數是this的新指向,第二個參數是fn要用到的參數數組,會立即執行fn函數。
3)fn.bind (newThis,params) bind函數的第一個參數是this的新指向,后面的參數可以直接傳遞,也可以按數組的形式傳入。 不會立即執行fn函數,且只能改變一次fn函數的指向,后續再用bind更改無效。返回的是已經更改this指向的新fn
我:呃~,好的,事件委托就是利用事件冒泡,只指定一個事件處理程序,就可以管理某一類型的所有事件。說白了就是將還沒有出現的事件,掛載到已經出現的事件上。整出代碼如下:
<body>
<ul id="ul">
<li>0</li>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<button id="btn">點我添加一個li</button>
<script>
// 事件委托
let ul = document.getElementById("ul")
ul.addEventListener('click',(event)=>{
console.log(event)
event = event || window.event
let target = event.target
if(target.nodeName == 'LI'){
alert(target.innerHTML)
}
})
let btn = document.getElementById('btn')
btn.addEventListener('click',()=>{
let li = document.createElement('li')
li.textContent = ul.children.length
ul.appendChild(li)
})
</script>
</body>
我:呃~,好的,Promise是ES6提供的一個構造函數,可以使用Promise構造函數new一個實例,Promise構造函數接收一個函數作為參數,這個函數有兩個參數,分別是兩個函數 resolve和reject,resolve將Promise的狀態由等待變為成功,將異步操作的結果作為參數傳遞過去;reject則將狀態由等待轉變為失敗,在異步操作失敗時調用,將異步操作報出的錯誤作為參數傳遞過去。實例創建完成后,可以使用then方法分別指定成功或失敗的回調函數,也可以使用catch捕獲失敗,then和catch最終返回的也是一個Promise,所以可以鏈式調用。
Promise的作用:
Promise是異步微任務,解決了異步多層嵌套回調的問題,讓代碼的可讀性更高,更容易維護 Promise使用
Promise的特點:
1)對象的狀態不受外界影響
2)一旦狀態改變,就不會再變,任何時候都可以得到這個結果
3)resolve 方法的參數是then中回調函數的參數,reject 方法中的參數是catch中的參數
4)then 方法和 catch方法 只要不報錯,返回的都是一個fullfilled狀態的promise
應用場景:
解決地獄回調問題
具體使用方法,參考我之前的文章:一文搞懂JS中的Promise
我:呃,好的,總結內容如下:
什么是跨域:
當前頁面中的某個接口請求的地址和當前頁面的地址如果協議、域名、端口其中有一項不同,就說該接口跨域了。
跨域限制的原因:瀏覽器為了保證網頁的安全,出的同源協議策略。
跨域解決方案:
cors:
目前最常用的一種解決辦法,通過設置后端允許跨域實現。
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader("Access-Control-Allow-Methods", "GET, PUT, OPTIONS, POST");node中間件、nginx反向代理:
跨域限制的時候瀏覽器不能跨域訪問服務器,node中間件和nginx反向代理,都是讓請求發給代理服務器,靜態頁面面和代理服務器是同源的,然后代理服務器再向后端服務器發請求,服務器和服務器之間不存在同源限制。
JSONP:利用的原理是script標簽可以跨域請求資源,將回調函數作為參數拼接在url中。后端收到請求,調用該回調函數,并將數據作為參數返回去,注意設置響應頭返回文檔類型,應該設置成javascript。
我:呃,好的,JavaScript有4種方法判斷變量的類型,總結如下:
typeof:
常用于判斷基本數據類型,對于引用數據類型除了function返回’function‘,其余全部返回’object'。
instanceof:
主要用于區分引用數據類型,檢測方法是檢測的類型在當前實例的原型鏈上,用其檢測出來的結果都是true
Object.prototype.toString.call()(對象原型鏈判斷方法):
適用于所有類型的判斷檢測,檢測方法是Object.prototype.toString.call(數據) 返回的是該數據類型的字符串。
constructor(用于引用數據類型):
用于檢測引用數據類型,檢測方法是獲取實例的構造函數判斷和某個類是否相同,如果相同就說明該數據是符合那個數據類型的,這種方法不會把原型鏈上的其他類也加入進來,避免了原型鏈的干擾。
我:呃~,好的,所有異步任務都是在同步任務執行結束之后,從任務隊列中依次取出執行。常見的實現異步的方式如下:
回調函數、事件監聽、setTimeout(定時器)、Promise、async/await,generator生成器
我:呃~,數組去重的方法有很多,舉幾個例子并簡單的加以說明,如下:
利用對象屬性key排除重復項:
遍歷數組,每次判斷對象中是否存在該屬性,不存在就存儲在新數組中,并且把數組元素作為key,設置一個值,存儲在對象中,最后返回新數組。
利用Set類型數據無重復項:
new 一個 Set,參數為需要去重的數組,Set 會自動刪除重復的元素,再將 Set 轉為數組返回。
filter+indexof 去重:
利用 Array 自帶的 filter 方法,返回 arr.indexOf(num) 等于 index 的num。
reduce +includes去重:
利用reduce遍歷和傳入一個空數組作為去重后的新數組,然后內部判斷新數組中是否存在當前遍歷的元素,不存在就插入到新數組中。
我:呃~,好的,箭頭函數相當于匿名函數,簡化了函數定義。箭頭函數有兩種寫法,當函數體是單條語句的時候可以省略{}和return。另一種是包含多條語句,不可以省略{}和return。 箭頭函數最大的特點就是沒有this,所以this是從外部獲取,就是繼承外部的執行上下文中的this,由于沒有this關鍵字所以箭頭函數也不能作為構造函數。
箭頭函數比普通函數的定義寫法更加簡潔明了和快捷。但是兩者又有區別:箭頭函數沒有原型prototype和super,所以無法創建this,其this是通過繼承外部函數環境中的變量獲取的,所以call、bind、apply都無法改變其this的指向;在找不到最外層的普通函數時,其this一般指向window;箭頭函數不能使用new;箭頭函數沒有arguments;也不能作為generator函數,不能使用yield命令;箭頭函數不能用于對象域和回調函數動態this中,一般用在內部沒有this引用。
我:呃~,好的,變量提升是指JS的變量和函數聲明會在代碼編譯期,提升到代碼的最前面。 變量提升成立的前提是使用Var關鍵字進行聲明的變量,并且變量提升的時候只有聲明被提升,賦值并不會被提升,同時函數的聲明提升會比變量的提升優先。 變量提升的結果,可以在變量初始化之前訪問該變量,返回的是undefined。在函數聲明前可以調用該函數。
使用let和const聲明的變量是創建提升,形成暫時性死區,在初始化之前訪問let和const創建的變量會報錯。
“web前端高頻面試題實例代碼分析”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。