久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

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

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

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

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

歷史發(fā)布:

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

01

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

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

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

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

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

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

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

02

閉包

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

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

作用:

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

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

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

03

原型和原型鏈

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

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

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

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

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

03

繼承

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

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

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

組合繼承

  // ----------------------方法二:組合繼承    // 在子函數(shù)中運行父函數(shù),,但是要利用call把this改變一下,    // 再在子函數(shù)的prototype里面new Father() ,使Father的原型中的方法也得到繼承,,最后改變Son的原型中的constructor
// 缺點:調(diào)用了兩次父類的構(gòu)造函數(shù),,造成了不必要的消耗,父類方法可以復(fù)用 // 優(yōu)點可傳參,,不共享父類引用屬性 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(寄生組合繼承的語法糖)    //     子類只要繼承父類,,可以不寫 constructor ,一旦寫了,,則在 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)存泄露、垃圾回收機制

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

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

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

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

垃圾回收機制都有哪些策略,??????

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

04

深拷貝和淺拷貝

手寫淺拷貝深拷貝?????

// ----------------------------------------------淺拷貝 // 只是把對象的屬性和屬性值拷貝到另一個對象中 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); //第一層的沒有被改變,,一層以下就被改變了

    // ----------------------------------------------深拷貝
// 簡易版 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);

// 簡易版存在的問題:參數(shù)沒有做檢驗,,傳入的可能是 Array、null,、regExp,、Date function deepClone2(o) { if (Object.prototype.toString.call(o) === '[object Object]') { //檢測是否為對象 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ù)升級,沒有考慮到數(shù)組,,以及ES6中的map,、set、weakset,、weakmap function deepClone3(o) { if (isObject(o)) {//檢測是否為對象或者數(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)引用問題 var a = {}; a.a = a; clone(a);//會造成一個死循環(huán) // 循環(huán)檢測 // 繼續(xù)升級 function deepClone4(o, hash = new map()) { if (!isObject(o)) return o//檢測是否為對象或者數(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)爆棧問題 // 將遞歸改為循環(huán),就不會出現(xià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()實現(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))) // 報錯 // Converting circular structure to JSON
版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,,轉(zhuǎn)載請附上原文出處鏈接和本聲明,。

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

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多