日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

搞懂90%,就可進(jìn)大廠的前端面試題(二) | 面經(jīng)分享

 skysun000001 2022-06-10 發(fā)布于北京
作者:晟小明
來(lái)源:CSDN博客

編者按:想進(jìn)大型互聯(lián)網(wǎng)公司總是需要掌握很多面試題,身為三本的本文作者,憑借這些前端面試題拿到了百度和京東的Offer。

作者用?標(biāo)記了標(biāo)題的重點(diǎn)程度,?越多越重點(diǎn)。下面我們就來(lái)看看這些能讓我們進(jìn)大廠的前端面試題吧。

歷史發(fā)布:

搞懂90%,就可進(jìn)大廠的前端面試題(一)

01

執(zhí)行棧和執(zhí)行上下文

什么是作用域,什么是作用域鏈?????

規(guī)定變量和函數(shù)的可使用范圍稱作作用域
每個(gè)函數(shù)都有一個(gè)作用域鏈,查找變量或者函數(shù)時(shí),需要從局部作用域到全局作用域依次查找,這些作用域的集合稱作作用域鏈。

什么是執(zhí)行棧,什么是執(zhí)行上下文?????

執(zhí)行上下文分為:

  • 全局執(zhí)行上下文
    • 創(chuàng)建一個(gè)全局的window對(duì)象,并規(guī)定this指向window,執(zhí)行js的時(shí)候就壓入棧底,關(guān)閉瀏覽器的時(shí)候才彈出
  • 函數(shù)執(zhí)行上下文
    • 每次函數(shù)調(diào)用時(shí),都會(huì)新創(chuàng)建一個(gè)函數(shù)執(zhí)行上下文
    • 執(zhí)行上下文分為創(chuàng)建階段和執(zhí)行階段
      • 創(chuàng)建階段:函數(shù)環(huán)境會(huì)創(chuàng)建變量對(duì)象:arguments對(duì)象(并賦值)、函數(shù)聲明(并賦值)、變量聲明(不賦值),函數(shù)表達(dá)式聲明(不賦值);會(huì)確定this指向;會(huì)確定作用域
      • 執(zhí)行階段:變量賦值、函數(shù)表達(dá)式賦值,使變量對(duì)象編程活躍對(duì)象
  • eval執(zhí)行上下文
執(zhí)行棧:

  • 首先棧特點(diǎn):先進(jìn)后出
  • 當(dāng)進(jìn)入一個(gè)執(zhí)行環(huán)境,就會(huì)創(chuàng)建出它的執(zhí)行上下文,然后進(jìn)行壓棧,當(dāng)程序執(zhí)行完成時(shí),它的執(zhí)行上下文就會(huì)被銷毀,進(jìn)行彈棧。
  • 棧底永遠(yuǎn)是全局環(huán)境的執(zhí)行上下文,棧頂永遠(yuǎn)是正在執(zhí)行函數(shù)的執(zhí)行上下文
  • 只有瀏覽器關(guān)閉的時(shí)候全局執(zhí)行上下文才會(huì)彈出

02

閉包

什么是閉包?閉包的作用?閉包的應(yīng)用??????

函數(shù)執(zhí)行,形成私有的執(zhí)行上下文,使內(nèi)部私有變量不受外界干擾,起到保護(hù)和保存的作用。

作用:

  • 保護(hù)
    • 避免命名沖突
  • 保存
    • 解決循環(huán)綁定引發(fā)的索引問(wèn)題
  • 變量不會(huì)銷毀
    • 可以使用函數(shù)內(nèi)部的變量,使變量不會(huì)被垃圾回收機(jī)制回收
應(yīng)用:

  • 設(shè)計(jì)模式中的單例模式
  • for循環(huán)中的保留i的操作
  • 防抖和節(jié)流
  • 函數(shù)柯里化
缺點(diǎn):

  • 會(huì)出現(xiàn)內(nèi)存泄漏的問(wèn)題

03

原型和原型鏈

什么是原型?什么是原型鏈?如何理解?????

原型:原型分為隱式原型和顯式原型,每個(gè)對(duì)象都有一個(gè)隱式原型,它指向自己的構(gòu)造函數(shù)的顯式原型。每個(gè)構(gòu)造方法都有一個(gè)顯式原型。

  • __proto__是隱式原型;prototype是顯式原型
  • 所有實(shí)例的__proto__都指向他們構(gòu)造函數(shù)的prototype
  • 所有的prototype都是對(duì)象,自然它的__proto__指向的是Object()的prototype
  • 所有的構(gòu)造函數(shù)的隱式原型指向的都是Function()的顯示原型
  • Object的隱式原型是null

原型鏈:多個(gè)__proto__組成的集合成為原型鏈(概念類似于作用域鏈)

  • instanceof 就是判斷某對(duì)象是否位于某構(gòu)造方法的原型鏈上。

03

繼承

說(shuō)一說(shuō) JS 中的常用的繼承方式有哪些?以及各個(gè)繼承方式的優(yōu)缺點(diǎn)。?????

原型繼承、組合繼承、寄生組合繼承、ES6的extend

原型繼承
// ----------------------方法一:原型繼承 // 原型繼承 // 把父類的實(shí)例作為子類的原型 // 缺點(diǎn):子類的實(shí)例共享了父類構(gòu)造函數(shù)的引用屬性 不能傳參 var person = { friends: ['a', 'b', 'c', 'd'] }
var p1 = Object.create(person)
    p1.friends.push('aaa')//缺點(diǎn):子類的實(shí)例共享了父類構(gòu)造函數(shù)的引用屬性
console.log(p1); console.log(person);//缺點(diǎn):子類的實(shí)例共享了父類構(gòu)造函數(shù)的引用屬性

組合繼承

  // ----------------------方法二:組合繼承    // 在子函數(shù)中運(yùn)行父函數(shù),但是要利用call把this改變一下,    // 再在子函數(shù)的prototype里面new Father() ,使Father的原型中的方法也得到繼承,最后改變Son的原型中的constructor
// 缺點(diǎn):調(diào)用了兩次父類的構(gòu)造函數(shù),造成了不必要的消耗,父類方法可以復(fù)用 // 優(yōu)點(diǎn)可傳參,不共享父類引用屬性 function Father(name) { this.name = name this.hobby = ['籃球', '足球', '乒乓球'] }
Father.prototype.getName = function () { console.log(this.name); }
function Son(name, age) { Father.call(this, name) this.age = age }
Son.prototype = new Father() Son.prototype.constructor = Son

var s = new Son('ming', 20)
    console.log(s);

寄生組合繼承

// ----------------------方法三:寄生組合繼承 function Father(name) { this.name = name this.hobby = ['籃球', '足球', '乒乓球']    }
Father.prototype.getName = function () { console.log(this.name); }
function Son(name, age) { Father.call(this, name) this.age = age    }
Son.prototype = Object.create(Father.prototype)    Son.prototype.constructor = Son
var s2 = new Son('ming', 18)    console.log(s2);
extend

// ----------------------方法四:ES6的extend(寄生組合繼承的語(yǔ)法糖)    //     子類只要繼承父類,可以不寫(xiě) constructor ,一旦寫(xiě)了,則在 constructor 中的第一句話    // 必須是 super 。    class Son3 extends Father { // Son.prototype.__proto__ = Father.prototype      constructor(y) {        super(200)  // super(200) => Father.call(this,200)        this.y = y      }    }

03

內(nèi)存泄露、垃圾回收機(jī)制

什么是內(nèi)存泄漏?????

內(nèi)存泄露是指不再用的內(nèi)存沒(méi)有被及時(shí)釋放出來(lái),導(dǎo)致該段內(nèi)存無(wú)法被使用就是內(nèi)存泄漏。

為什么會(huì)導(dǎo)致的內(nèi)存泄漏?????

內(nèi)存泄漏指我們無(wú)法在通過(guò)js訪問(wèn)某個(gè)對(duì)象,而垃圾回收機(jī)制卻認(rèn)為該對(duì)象還在被引用,因此垃圾回收機(jī)制不會(huì)釋放該對(duì)象,導(dǎo)致該塊內(nèi)存永遠(yuǎn)無(wú)法釋放,積少成多,系統(tǒng)會(huì)越來(lái)越卡以至于崩潰。

垃圾回收機(jī)制都有哪些策略??????

  • 標(biāo)記清除法
    • 垃圾回收機(jī)制獲取根并標(biāo)記他們,然后訪問(wèn)并標(biāo)記所有來(lái)自它們的引用,然后在訪問(wèn)這些對(duì)象并標(biāo)記它們的引用…如此遞進(jìn)結(jié)束后若發(fā)現(xiàn)有沒(méi)有標(biāo)記的(不可達(dá)的)進(jìn)行刪除,進(jìn)入執(zhí)行環(huán)境的不能進(jìn)行刪除
  • 引用計(jì)數(shù)法
    • 當(dāng)聲明一個(gè)變量并給該變量賦值一個(gè)引用類型的值時(shí)候,該值的計(jì)數(shù) 1,當(dāng)該值賦值給另一個(gè)變量的時(shí)候,該計(jì)數(shù) 1,當(dāng)該值被其他值取代的時(shí)候,該計(jì)數(shù)-1,當(dāng)計(jì)數(shù)變?yōu)?的時(shí)候,說(shuō)明無(wú)法訪問(wèn)該值了,垃圾回收機(jī)制清除該對(duì)象
    • 缺點(diǎn):當(dāng)兩個(gè)對(duì)象循環(huán)引用的時(shí)候,引用計(jì)數(shù)無(wú)計(jì)可施。如果循環(huán)引用多次執(zhí)行的話,會(huì)造成崩潰等問(wèn)題。所以后來(lái)被標(biāo)記清除法取代。

04

深拷貝和淺拷貝

手寫(xiě)淺拷貝深拷貝?????

// ----------------------------------------------淺拷貝 // 只是把對(duì)象的屬性和屬性值拷貝到另一個(gè)對(duì)象中 var obj1 = { a: { a1: { a2: 1 }, a10: { a11: 123, a111: { a1111: 123123 } } }, b: 123, c: '123' } // 方式1 function shallowClone1(o) { let obj = {}
for (let i in o) { obj[i] = o[i] } return obj } // 方式2 var shallowObj2 = { ...obj1 } // 方式3    var shallowObj3 = Object.assign({}, obj1)
let shallowObj = shallowClone1(obj1);
shallowObj.a.a1 = 999 shallowObj.b = true
console.log(obj1); //第一層的沒(méi)有被改變,一層以下就被改變了

    // ----------------------------------------------深拷貝
// 簡(jiǎn)易版 function deepClone(o) { let obj = {} for (var i in o) { // if(o.hasOwnProperty(i)){ if (typeof o[i] === 'object') { obj[i] = deepClone(o[i]) } else { obj[i] = o[i] } // } } return obj }

var myObj = { a: { a1: { a2: 1 }, a10: { a11: 123, a111: { a1111: 123123 } } }, b: 123, c: '123' }
var deepObj1 = deepClone(myObj) deepObj1.a.a1 = 999 deepObj1.b = false    console.log(myObj);

// 簡(jiǎn)易版存在的問(wèn)題:參數(shù)沒(méi)有做檢驗(yàn),傳入的可能是 Array、null、regExp、Date function deepClone2(o) { if (Object.prototype.toString.call(o) === '[object Object]') { //檢測(cè)是否為對(duì)象 let obj = {} for (var i in o) { if (o.hasOwnProperty(i)) { if (typeof o[i] === 'object') { obj[i] = deepClone(o[i]) } else { obj[i] = o[i] } } } return obj } else { return o }    }
function isObject(o) { return Object.prototype.toString.call(o) === '[object Object]' || Object.prototype.toString.call(o) === '[object Array]' } // 繼續(xù)升級(jí),沒(méi)有考慮到數(shù)組,以及ES6中的map、set、weakset、weakmap function deepClone3(o) { if (isObject(o)) {//檢測(cè)是否為對(duì)象或者數(shù)組 let obj = Array.isArray(o) ? [] : {} for (let i in o) { if (isObject(o[i])) { obj[i] = deepClone(o[i]) } else { obj[i] = o[i] } } return obj } else { return o }    }

// 有可能碰到循環(huán)引用問(wèn)題 var a = {}; a.a = a; clone(a);//會(huì)造成一個(gè)死循環(huán) // 循環(huán)檢測(cè) // 繼續(xù)升級(jí) function deepClone4(o, hash = new map()) { if (!isObject(o)) return o//檢測(cè)是否為對(duì)象或者數(shù)組 if (hash.has(o)) return hash.get(o) let obj = Array.isArray(o) ? [] : {}
hash.set(o, obj) for (let i in o) { if (isObject(o[i])) { obj[i] = deepClone4(o[i], hash) } else { obj[i] = o[i] } } return obj    }
// 遞歸易出現(xiàn)爆棧問(wèn)題 // 將遞歸改為循環(huán),就不會(huì)出現(xiàn)爆棧問(wèn)題了 var a1 = { a: 1, b: 2, c: { c1: 3, c2: { c21: 4, c22: 5 } }, d: 'asd' }; var b1 = { b: { c: { d: 1 } } } function cloneLoop(x) { const root = {}; // 棧 const loopList = [ //->[]->[{parent:{a:1,b:2},key:c,data:{ c1: 3, c2: { c21: 4, c22: 5 } }}] { parent: root, key: undefined, data: x, } ]; while (loopList.length) { // 深度優(yōu)先 const node = loopList.pop(); const parent = node.parent; //{} //{a:1,b:2} const key = node.key; //undefined //c const data = node.data; //{ a: 1, b: 2, c: { c1: 3, c2: { c21: 4, c22: 5 } }, d: 'asd' } //{ c1: 3, c2: { c21: 4, c22: 5 } }} // 初始化賦值目標(biāo),key 為 undefined 則拷貝到父元素,否則拷貝到子元素 let res = parent; //{}->{a:1,b:2,d:'asd'} //{a:1,b:2}->{} if (typeof key !== 'undefined') { res = parent[key] = {}; } for (let k in data) { if (data.hasOwnProperty(k)) { if (typeof data[k] === 'object') { // 下一次循環(huán) loopList.push({ parent: res, key: k, data: data[k], }) } else { res[k] = data[k]; } } } } return root }

function deepClone5(o) { let result = {} let loopList = [ { parent: result, key: undefined, data: o } ]
while (loopList.length) { let node = loopList.pop() let { parent, key, data } = node let anoPar = parent if (typeof key !== 'undefined') { anoPar = parent[key] = {} }
for (let i in data) { if (typeof data[i] === 'object') { loopList.push({ parent: anoPar, key: i, data: data[i] }) } else { anoPar[i] = data[i] } } } return result }

let cloneA1 = deepClone5(a1) cloneA1.c.c2.c22 = 5555555 console.log(a1); console.log(cloneA1);
// ------------------------------------------JSON.stringify()實(shí)現(xiàn)深拷貝 function cloneJson(o) { return JSON.parse(JSON.stringify(o)) } // let obj = { a: { c: 1 }, b: {} }; // obj.b = obj; // console.log(JSON.parse(JSON.stringify(obj))) // 報(bào)錯(cuò) // Converting circular structure to JSON
版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接和本聲明。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多