編者按:想進(jìn)大型互聯(lián)網(wǎng)公司總是需要掌握很多面試題,身為三本的本文作者,,憑借這些前端面試題拿到了百度和京東的Offer。 作者用?標(biāo)記了標(biāo)題的重點程度,,?越多越重點,。下面我們就來看看這些能讓我們進(jìn)大廠的前端面試題吧。 歷史發(fā)布: 搞懂90%,,就可進(jìn)大廠的前端面試題(一) 01執(zhí)行棧和執(zhí)行上下文什么是作用域,,什么是作用域鏈?????什么是執(zhí)行棧,,什么是執(zhí)行上下文,?????
02閉包什么是閉包,?閉包的作用,?閉包的應(yīng)用??????
03原型和原型鏈什么是原型?什么是原型鏈,?如何理解?????
03繼承說一說 JS 中的常用的繼承方式有哪些?以及各個繼承方式的優(yōu)缺點,。?????// ----------------------方法一:原型繼承 // 原型繼承 // 把父類的實例作為子類的原型 // 缺點:子類的實例共享了父類構(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ù)的引用屬性
// ----------------------方法三:寄生組合繼承 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);
03內(nèi)存泄露、垃圾回收機制什么是內(nèi)存泄漏?????為什么會導(dǎo)致的內(nèi)存泄漏?????垃圾回收機制都有哪些策略,??????
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 |
|