前端常見問題總結(jié)

什么是閉包?閉包的用途是什么鸠澈?閉包的缺點是什么白对?

什么是閉包

閉包:內(nèi)部函數(shù)總是可以訪問其所在的外部函數(shù)中聲明的參數(shù)和變量。聲明在一個函數(shù)中的函數(shù)握联,叫做閉包函數(shù)。
存在不被釋放或者互相引用的場景都可以叫做閉包每瞒。
代碼舉例:

function Counter(){
    let num = 0
    function add(){
        num++
        console.log(num)
    }
    return add
}
let addOne = Counter()
addOne()//1
addOne()//2

在Counter函數(shù)中創(chuàng)建了一個add函數(shù)金闽,且add函數(shù)中用到了Counter函數(shù)的num變量,這就使得num和add函數(shù)構(gòu)成了一個閉包剿骨。這個變量num一直存在于內(nèi)中代芜,我們很難在外部訪問num變量,但是我們可以通過操作內(nèi)部的函數(shù)來控制它浓利。

閉包的用途
  1. 隱藏變量挤庇,只通過制定接口訪問數(shù)據(jù)
const cache = (() => {
 const store = {}
 return {
     get(key) {
         return store[key]
     },
     set(key, val) {
         store[key] = val
     },
     remove(key) {
         delete store[key]
     }
 }
})()

這個箭頭函數(shù)我們會得到一個對象钞速,我會得到它的get,set和remove方法嫡秕,我們打印這個cache的時候只會看到get渴语,set和remove三個屬性,store就被我們隱藏起來了昆咽。但是我們可以通過get驾凶,set和remove來操作store。

  1. 存儲臨時變量
function sum(a){
 return function(b){
     return a+b
 }
}
const sum1 = sum(1)
const sum2 = sum(2)
console.log(sum1(3))//4
console.log(sum2(3))//5

聲明好的sum1和sum2就會隱藏在閉包里掷酗,當(dāng)我們在調(diào)用sum1(3)的時候就自動加上了sum1调违,同理在調(diào)用sum2(3)的時候,也自動加上了sum2汇在。sum1和sum2就存儲了一個臨時的數(shù)據(jù)給我們用翰萨。

  1. 讓對象擁有私有屬性
 constructor() {
     let name
     Object.assign(this,{
         setName(newName){
             name = newName
         },
         getName(){
             return name
         }
     })
 }
 sayHi(){
     console.log(`Hi,${this.getName()}`)
 }
}
let p1 = new People
p1.setName('qyk')
p1.getName()//'qyk'
p1.sayHi()//"Hi,qyk"

sayHi()調(diào)用了上層的name,是個閉包糕殉。同時也讓p1有了私有屬性。

  1. 調(diào)用一個函數(shù)返回另一個函數(shù)
閉包的缺點
  1. 由于閉包會使得函數(shù)中的變量都被保存在內(nèi)存中殖告,內(nèi)存消耗很大阿蝶,所以不能濫用閉包,否則會造成網(wǎng)頁的性能問題黄绩,在IE中可能導(dǎo)致內(nèi)存泄露羡洁。解決方法是,在退出函數(shù)之前爽丹,將不使用的局部變量全部刪除筑煮。
  2. 閉包會在父函數(shù)外部,改變父函數(shù)內(nèi)部變量的值粤蝎。所以真仲,如果你把父函數(shù)當(dāng)作對象使用,把閉包當(dāng)作它的公用方法初澎,把內(nèi)部變量當(dāng)作它的私有屬性秸应,這時一定要小心,不要隨便改變父函數(shù)內(nèi)部變量的值碑宴。

call软啼、apply、bind 的用法分別是什么延柠?

call

call 方法第一個參數(shù)是要綁定給this的值祸挪,后面?zhèn)魅氲氖且粋€參數(shù)列表。當(dāng)?shù)谝粋€參數(shù)為null贞间、
undefined的時候贿条,默認指向window雹仿。

function add(a,b){
  return a+b;
}
function.call(add,1,2)//3 其中1和2是連續(xù)的參數(shù)
apply

apply接受兩個參數(shù),第一個參數(shù)是要綁定給this的值闪唆,第二個參數(shù)是一個參數(shù)數(shù)組盅粪。當(dāng)?shù)谝粋€參數(shù)為
null、undefined的時候悄蕾,默認指向window票顾。

function add(a,b){
  return a+b;
}
funciton.apply(add,[1,2]//3 其中1和2數(shù)參數(shù)數(shù)組

當(dāng)函數(shù)需要傳遞多個變量時, apply 可以接受一個數(shù)組作為參數(shù)輸入, call 則是接受一系列的單獨變量。

bind

第一個參數(shù)是this的指向帆调,從第二個參數(shù)開始是接收的參數(shù)列表奠骄。bind 方法不會立即執(zhí)行,而是返回一個改變了上下文 this 后的函數(shù)番刊。

fn.bind(x,y,z) 不會執(zhí)行 fn含鳞,而是會返回一個新的函數(shù)
新的函數(shù)執(zhí)行時,會調(diào)用 fn芹务,調(diào)用形式為 fn.call(x, y, z)蝉绷,其中 x 是 this,y 和z 是其他參數(shù)

function add(a, b){
  return a+b;
}
var foo1 = add.bind(add, 1,2); 
foo1(); //3 只有調(diào)用才會執(zhí)行

在 ES6 的箭頭函數(shù)下, call 和 apply 將失效枣抱。


請說出至少 10 個 HTTP 狀態(tài)碼熔吗,并描述各狀態(tài)碼的意義。

  1. 狀態(tài)碼100表示繼續(xù)佳晶∥荩客戶端應(yīng)繼續(xù)其請求
  2. 狀態(tài)碼101表示切換協(xié)議。服務(wù)器根據(jù)客戶端的請求切換協(xié)議
  3. 狀態(tài)碼200表示請求成功轿秧。一般用于GET與POST請求
  4. 狀態(tài)碼201表示已創(chuàng)建中跌。成功請求并創(chuàng)建了新的資源
  5. 狀態(tài)碼202表示已接受。已經(jīng)接受請求菇篡,但未處理完成
  6. 狀態(tài)碼203表示非授權(quán)信息漩符。請求成功。但返回的meta信息不在原始的服務(wù)器逸贾,而是一個副本
  7. 狀態(tài)碼300表示多種選擇陨仅。請求的資源可包括多個位置,相應(yīng)可返回一個資源特征與地址的列表用于用戶終端(例如:瀏覽器)選擇
  8. 狀態(tài)碼303表示查看其它地址
  9. 狀態(tài)碼305表示使用代理铝侵。所請求的資源必須通過代理訪問
  10. 狀態(tài)碼306表示已經(jīng)被廢棄的HTTP狀態(tài)碼
  11. 狀態(tài)碼400表示客戶端請求的語法錯誤灼伤,服務(wù)器無法理解
  12. 狀態(tài)碼403表示服務(wù)器理解請求客戶端的請求,但是拒絕執(zhí)行此請求
  13. 狀態(tài)碼404表示服務(wù)器無法根據(jù)客戶端的請求找到資源(網(wǎng)頁)

如何實現(xiàn)數(shù)組去重咪鲜?

假設(shè)有數(shù)組 array = [1,5,2,3,4,2,3,1,3,4]
你要寫一個函數(shù) unique狐赡,使得
unique(array) 的值為 [1,5,2,3,4]
也就是把重復(fù)的值都去掉,只保留不重復(fù)的值疟丙。

使用indexOf

思路:新建一個空的結(jié)果數(shù)組颖侄,for 循環(huán)原數(shù)組鸟雏,判斷結(jié)果數(shù)組是否存在當(dāng)前元素,
如果有相同的值則跳過览祖,不相同則push進數(shù)組孝鹊。

let arr = [1, 5, 2, 3, 4, 2, 3, 1, 3, 4]
function unique(arr) {
 let array = [];
 for (let i = 0; i < arr.length; i++) {    // 首次遍歷數(shù)組
     if (array.indexOf(arr[i]) === -1) {   // 判斷索引有沒有等于
         array.push(arr[i])
     }
 }
 return array
}
console.log(unique(arr));

缺點:無法對NaN和對象去重

使用set
let arr = [1, 5, 2, 3, 4, 2, 3, 1, 3, 4]
function unique (arr) {
 return Array.from(new Set(arr))
}
console.log(unique(arr))

缺點:無法去重對象,且有兼容性問題展蒂。API太新又活,舊瀏覽器不支持

使用map
function unique(arr) {
    const map = new Map()
    const newArr = []

    arr.forEach(item => {
        if (!map.has(item)) { // has()用于判斷map是否包為item的屬性值
            map.set(item, true) // 使用set()將item設(shè)置到map中,并設(shè)置其屬性值為true
            newArr.push(item)
        }
    })

    return newArr
}

console.log(unique(arr))

缺點:API 太新锰悼,舊瀏覽器不支持柳骄。


DOM 事件相關(guān)

什么是事件委托

由于事件會在冒泡階段向上傳播到父節(jié)點,因此可以把子節(jié)點的監(jiān)聽函數(shù)定義在父節(jié)點上箕般,由父節(jié)點的監(jiān)聽函數(shù)統(tǒng)一處理多個子元素的事件耐薯。這種方法叫做事件委托。 通俗點講就是委托一個元素幫我監(jiān)聽我本該監(jiān)聽的元素丝里。

怎么阻止默認動作

w3c的方法是e.preventDefault()曲初,IE則是使用e.returnValue = false

<a  id="testA" >caibaojian.com</a>
 var a = document.getElementById("testA");
 a.onclick =function(e){
     if(e.preventDefault){
         e.preventDefault();//W3C
     }else{
         window.event.returnValue = false;//IE
     }
}
怎么阻止事件冒泡

w3c使用e.stopPropagation(),IE使用e.cancelBubble = true

 function stopBubble(e) { 
     if ( e && e.stopPropagation ){ 
         e.stopPropagation(); //W3C
     }else{ 
         window.event.cancelBubble = true; //IE
     }
}

如何理解 JS 的繼承杯聚?

基于原型的繼承

實例化一個新的函數(shù)复斥,子類的原型指向了父類的實例,子類就可以調(diào)用其父類原型對象上的共有屬性械媒。

function Parent() {
    this.parentName = '父類';
}
Parent.prototype.getParentName = function() {
    return this.parentName;
};

function Child() {
    this.childName = '子類';
}
Child.prototype = new Parent();//繼承Parent
Child.prototype.getChildName = function() {
    return this.childName
};

let c = new Child();
console.log(c.getParentName()); // '父類'
function Parent(name1){
  this.name1 = name1
}
Parent.prototype.pMethod = function(){
  console.log(this.name1)
}

function Child(name2, name1){
    Parent.call(this, name1) // 得分點
    this.name2 = name2
}
Child.prototype.__proto__ = Parent.prototype 
Child.prototype.cMethod = function(){
    console.log(this.name2)
}

缺點:子類的實例可以訪問父類的私有屬性,子類的實例還可以更改該屬性评汰,不安全

基于class的繼承

如需創(chuàng)建類繼承纷捞,使用 extends 關(guān)鍵字。

class Parent{
    constructor(name1){
        this.name1 = name1
    }
    pMethod(){
        console.log(this.name1)
    }
}
class Child extends Parent{
    constructor(name2, name1){
        super(name1) // 得分點
        this.name2 = name2
    }
    cMethod(){
        console.log(this.name2)
    }
}

數(shù)組排序

給出正整數(shù)數(shù)組 array = [2,1,5,3,8,4,9,5]
請寫出一個函數(shù) sort被去,使得 sort(array) 得到從小到大排好序的數(shù)組 [1,2,3,4,5,5,8,9]
新的數(shù)組可以是在 array 自身上改的主儡,也可以是完全新開辟的內(nèi)存。

let min = (numbers)=>{
    if(numbers.length>2){
        return min([numbers[0],min(numbers.slice(1))])
    }else {
        return Math.min.apply(null,numbers)
    }
}//求出最小值的算法
let minIndex = (numbers) =>
    numbers.indexOf(min(numbers))//標(biāo)記最小值

let sort = (numbers)=>{
    if(numbers.length>2){
        let index = minIndex(numbers)
        let min = numbers[index]
        numbers.splice(index,1)
        return [min].concat(sort(numbers))
    }else{
        return numbers[0]<numbers[1]? numbers :numbers.reverse()
    }
}
let array =[2,1,5,3,8,4,9,5]
sort(array)

對 Promise 的了解惨缆?

promise的用途

Promise 用于避免回調(diào)地域糜值,讓代碼看起來更同步

創(chuàng)建一個 new Promise
function fn(){
    return new Promise((resolve, reject)=>{
        成功時調(diào)用 resolve(data)
        失敗時調(diào)用 reject(reason)
    })
}
使用 Promise.prototype.then
const promise1 = fn() // 得到 promise1 對象
fn().then(success, fail).then(success2, fail2).catch(fail3)
或者
promise1.then(success, fail).then(success2, fail2).catch(fail3)
均可
使用Promise.all
Promise.all([promise1, promise2]) 并行,等待所有 promise 成功坯墨。
如果都成功了寂汇,則 all 對應(yīng)的 promise 也成功;如果有一個失敗了捣染,則 all 對應(yīng)的 promise 失敗骄瓣。
使用 Promise.race
Promise.race([promise1, promise2]),返回一個
promise耍攘,一旦數(shù)組中的某個promise解決或拒絕榕栏,返回的 promise就會解決或拒絕畔勤。

說說跨域

什么是同源

源:協(xié)議+域名+端口號
Window.origin或者location.origin可以得到當(dāng)前的源
兩個URL的協(xié)議、域名和端口號完全一致那么這兩個URL就是同源
同源策略就是扒磁,瀏覽器規(guī)定:如果JS運行在源A里庆揪,那么就只能獲取源A的數(shù)據(jù),不能獲取源B的數(shù)據(jù)妨托,
即不允許跨域缸榛。這是瀏覽器的功能。瀏覽器為了主動預(yù)防偷數(shù)據(jù)的問題始鱼,設(shè)置了嚴(yán)格的同源策略

什么是跨域

跨域仔掸,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。
它是由瀏覽器的同源策略造成的医清,是瀏覽器對JavaScript實施的安全限制起暮。
當(dāng)一個請求url的協(xié)議、域名会烙、端口三者之間任意一個與當(dāng)前頁面url不同即為跨域负懦。

JSONP跨域

我們在跨域的時候,由于當(dāng)前瀏覽器不支持CORS柏腻,或者因為某些條件不支持CORS纸厉,我們必須使用一種方法來進行跨域。于是我們請求一個JS文件五嫂,這個JS文件回執(zhí)行一個回調(diào)颗品,回調(diào)里面有我們的數(shù)據(jù)∥衷担回調(diào)的名字可以通過隨機數(shù)生成的躯枢,我們把這個隨機數(shù)以callback的參數(shù)傳給后臺,后臺會把函數(shù)返回給我們并且執(zhí)行槐臀。
缺點:由于它是一個script標(biāo)簽锄蹂,所以讀不到AJAX那么精確的status值,無法知道狀態(tài)碼是什么水慨,也只能發(fā)送GET請求得糜,JSONP不支持POST

CORS跨域

CORS(跨域資源共享)
跨源資源共享 (CORS)是一種基于 HTTP 頭的機制,該機制通過允許服務(wù)器標(biāo)示除了它自己以外的其它 origin(域晰洒,協(xié)議和端口)朝抖,使得瀏覽器允許這些 origin 訪問加載自己的資源。瀏覽器默認不同源之間不能互相訪問數(shù)據(jù)欢顷,但是我們想讓兩個網(wǎng)站互相訪問槽棍。我們就用CORS,如果要共享數(shù)據(jù)就需要提前聲明。例如炼七,源B要訪問源A缆巧,源A就要在響應(yīng)頭里聲明源B可以訪問:
response.setHeader("Access-Control-Allow-Origin","http://foo.example")

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市豌拙,隨后出現(xiàn)的幾起案子陕悬,更是在濱河造成了極大的恐慌,老刑警劉巖按傅,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捉超,死亡現(xiàn)場離奇詭異,居然都是意外死亡唯绍,警方通過查閱死者的電腦和手機拼岳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來况芒,“玉大人惜纸,你說我怎么就攤上這事【В” “怎么了耐版?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長压汪。 經(jīng)常有香客問我粪牲,道長,這世上最難降的妖魔是什么止剖? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任腺阳,我火速辦了婚禮,結(jié)果婚禮上穿香,老公的妹妹穿的比我還像新娘舌狗。我一直安慰自己,他們只是感情好扔水,可當(dāng)我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著朝氓,像睡著了一般魔市。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上赵哲,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天待德,我揣著相機與錄音,去河邊找鬼枫夺。 笑死将宪,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播较坛,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼印蔗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了丑勤?” 一聲冷哼從身側(cè)響起华嘹,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎法竞,沒想到半個月后耙厚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡岔霸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年薛躬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呆细。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡型宝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出侦鹏,到底是詐尸還是另有隱情诡曙,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布略水,位于F島的核電站价卤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏渊涝。R本人自食惡果不足惜慎璧,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望跨释。 院中可真熱鬧胸私,春花似錦、人聲如沸鳖谈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缆娃。三九已至捷绒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間贯要,已是汗流浹背暖侨。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留崇渗,地道東北人字逗。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓京郑,卻偏偏與公主長得像,于是被迫代替她去往敵國和親葫掉。 傳聞我的和親對象是個殘疾皇子些举,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容