前端面试instanceof_一起回归一下每日一题这些经典面试题
需求已改活已加,加班通宵看朝霞。終是上線已延期,bug還是改不完。
面試造火箭,工作擰螺絲,雖然我只想擰螺絲,可是我需要用造火箭的技術去尋找擰螺絲的工作,如何能在面試過程中讓自己處于不敗的地步呢,刷題是一個比較好的捷徑,今天就匯總了一些比較經典的面試題進行了匯總,分享給大家。
題目一
題目介紹
如下為一段代碼,請完善sum函數,使得 sum(1,2,3,4,5,6) 函數返回值為 21 ,需要在 sum 函數中調用 asyncAdd 函數,且不能修改asyncAdd函數
/*** 請在 sum函數中調用此函數,完成數值計算
* @param {*} a 要相加的第一個值
* @param {*} b 要相加的第二個值
* @param {*} callback 相加之后的回調函數
*/
function asyncAdd(a,b,callback) {
setTimeout(function(){
callback(null, a+b)
},100)
}
/**
* 請在此方法中調用asyncAdd方法,完成數值計算
* @param {...any} rest 傳入的參數
*/
async function sum(...rest) {
// 請在此處完善代碼
}
let start = window.performance.now()
sum(1, 2, 3, 4, 5, 6).then(res => {
// 請保證在調用sum方法之后,返回結果21
console.log(res)
console.log(`程序執行共耗時: ${window.performance.now() - start}`)
})
本題根據程序輸出時間不同,可以劃分為三個難度等級
答案
// 取出來第一個作為初始值
let result = rest.shift()
// 通過for of 遍歷 rest, 依次相加
for(let num of rest) {
// 使用promise 獲取相加結果
result = await new Promise(resolve => {
asyncAdd(result, num, (_,res) => {
resolve(res)
})
})
}
// 返回執行結果
return result
}
// 執行成功,執行時長大于6秒
sum1(1, 2, 3, 4, 5,6).then(res => {
console.log(`計算結果為:${res}`)
})
在青銅難度,我們把數組里面的每一項依次相加。但是也可以進行一些優化,可以并發執行多個,比如 sum(1,2,3,4,5,6),可以同時執行 1+2,3+4,5+6,這樣就可以提升執行效率
async function sum(...rest) {// 如果傳的值少于2個,則直接返回
if (rest.length <= 1) {
return rest[0] || 0
}
const promises = []
// 遍歷將數組里面的值兩個兩個的執行
for (let i = 0; i < rest.length; i += 2) {
promises.push(
new Promise(resolve => {
// 如果 rest[i+1] 是 undefined, 說明數組長度是奇數,這個是最后一個
if (rest[i + 1] === undefined) {
resolve(rest[i])
} else {
// 調用asyncAdd 進行計算
asyncAdd(rest[i], rest[i + 1], (_, result) => {
resolve(result)
})
}
})
)
}
// 獲取第一次計算結果
const result = await Promise.all(promises)
// 然后將第一次獲取到的結果即 [3,7,11] 再次調用 sum執行
return await sum(...result)
}
// 執行成功,執行時長大于3秒小于4秒
sum1(1, 2, 3, 4, 5,6).then(res => {
console.log(`計算結果為:${res}`)
})
let result = 0
// 隱氏類型轉換, 對象 + 數字,會先調用對象的toString 方法
const obj = {}
obj.toString = function() {
return result
}
const promises = []
for(let num of rest) {
promises.push(new Promise((resolve) => {
asyncAdd(obj, num, (_, res) => {
resolve(res)
})
}).then(res => {
// 在這里將 result的值改變之后,obj.toString 的返回值就變了,這時候下一個setTimeout調用時就使用了新值
result = res
}))
}
await Promise.all(promises)
return result
}
// 執行成功,執行時長大于1秒小于2秒
sum1(1, 2, 3, 4, 5,6).then(res => {
console.log(`計算結果為:${res}`)
})
因為js是執行在單線程里面的,所以上面的代碼,我們在for of將所有的計算放到promises數組里面,然后通過Promise.all去一次性執行,這時候并不需要考慮到底先執行哪兩個數字相加。因為單線程的原因,我們可以保證這幾個Promise是依次執行的,這時候obj.toString返回值就是上一個Promise的返回值,多跑幾遍代碼你就懂了哦
題目二
題目介紹
請說明以下代碼各輸出了什么?
console.log(typeof (() => {}))console.log(typeof ['前端有的玩','公眾號'])
console.log(typeof null)
console.log(typeof undefined)
console.log(typeof Function.prototype)
console.log('子君' instanceof String)
console.log(new Date() instanceof Date)
答案
// 輸出 functionconsole.log(typeof (() => {}))
// 輸出 object
console.log(typeof ['前端有的玩','公眾號'])
// 輸出 object
console.log(typeof null)
// 輸出 undefined
console.log(typeof undefined)
// 輸出 function
console.log(typeof Function.prototype)
// 輸出 false
console.log('子君' instanceof String)
// 輸出 true
console.log(new Date() instanceof Date)
需要注意的是,對于 typeof, 可以正確判斷除了null之外的所有基本類型,而對于引用類型,除了函數外其他都會被判斷為object。
對于instanceof,無法判斷基本類型,但可以正確判斷引用類型
題目三
題目介紹
請實現一個instanceof,讓以下代碼可正常運行
/**自定義instanceof
*/
function instanceOf(left, right) {
// 請完善以下代碼,不能使用原生instanceof
}
class A{}
class B extends A {}
class C{}
const b = new B()
// 輸出 true
console.log(instanceOf(b,B))
// 輸出 true
console.log(instanceOf(b,A))
// 輸出 false
console.log(instanceOf(b,C))
答案
本題主要考察instanceof的判斷原理,instanceof主要的實現原理就是只要右邊變量的 prototype 在左邊變量的原型鏈上即可。因此,instanceof 在查找的過程中會遍歷左邊變量的原型鏈,直到找到右邊變量的 prototype,如果查找失敗,則會返回 false。
/**自定義instanceof
*/
function instanceOf(left, right) {
let proto = left.__proto__
while(proto){
if(proto === right.prototype){
return true
}
proto = proto.__proto__
}
return false
}
class A{}
class B extends A {}
class C{}
const b = new B()
// 輸出 true
console.log(instanceOf(b,B))
// 輸出 true
console.log(instanceOf(b,A))
// 輸出 false
console.log(instanceOf(b,C))
題目四
題目介紹
請模擬實現new操作符,使下面代碼正常運行
function myNew(constructor, ...rest) {// 請在此處完善代碼,不能直接使用 new 操作符
}
function Fun(name,sex) {
this.name = name
this.sex = sex
}
Fun.prototype.getUserInfo = function() {
return `我的姓名${this.name},我的性別${this.sex}`
}
const fun = myNew(Fun,'子君','男')
// 我的姓名子君,我的性別男
console.log(fun.getUserInfo())
答案
這道題考察的是使用new操作符調用構造函數所經歷的階段:
if (typeof constructor !== 'function') {
return constructor;
}
//創建新的對象,關聯構造函數的原型對象
const _constructor = Object.create(constructor.prototype);
//執行構造函數
const obj = constructor.apply(_constructor, rest);
//如果構造函數執行結果是對象則返回執行結果
if (typeof obj === 'object') {
return obj;
} else {
return _constructor;
}
}
function Fun(name,sex) {
this.name = name
this.sex = sex
}
Fun.prototype.getUserInfo = function() {
return `我的姓名${this.name},我的性別${this.sex}`
}
const fun = myNew(Fun,'子君','男')
// 我的姓名子君,我的性別男
console.log(fun.getUserInfo())
題目五
題目介紹
請說出以下代碼輸出內容
const a = {}const b = Symbol('1')
const c = Symbol('1')
a[b] = '子君'
a[c] = '君子'
// 我是子君還是君子呢
console.log(a[b])
const d = {}
const e = {key: '1'}
const f = {key: '2'}
d[e] = '子君'
d[f] = '君子'
// 我是子君還是君子呢
console.log(d[e])
答案
const a = {}const b = Symbol('1')
const c = Symbol('1')
a[b] = '子君'
a[c] = '君子'
// 輸出子君
console.log(a[b])
const d = {}
const e = {key: '1'}
const f = {key: '2'}
d[e] = '子君'
d[f] = '君子'
// 輸出君子
console.log(d[e])
對于第一個輸出,Symbol()函數會返回**「symbol」**類型的值,而Symbol函數傳的參數僅僅是用于標識的,不會影響值的唯一性
對于第二個輸出, 因為e和f都是對象,而對象的key只能是數值或字符,所以會將對象轉換為字符,對象的toString方法返回的是[object Object], 所有輸出的是君子
題目六
題目介紹
請說出以下代碼輸出的內容
console.log([] + [])console.log({} + [])
console.log([] == ![])
console.log(true + false)
答案
console.log([] + [])
這行代碼輸出的是空字符串"", 包裝類型在運算的時候,會先調用valueOf方法,如果valueOf返回的還是包裝類型,那么再調用toString方法
// 還是 數組const val = [].valueOf()
// 數組 toString 默認會將數組各項使用逗號 "," 隔開, 比如 [1,2,3].toSting 變成了"1,2,3",空數組 toString 就是空字符串
const val1 = val.toString() // val1 是空字符串
所以上面的代碼相當于
console.log("" + "")第二行代碼
// 輸出 "[object Object]"console.log({} + [])
和第一題道理一樣,對象 {}隱氏轉換成了[object Object],然后與""相加
第三行代碼
// 輸出 trueconsole.log([] == ![])
對于===, 會嚴格比較兩者的值,但是對于==就不一樣了
所以對于上面的代碼,看下面一步一步分析
// 這個輸出 falseconsole.log(![])
// 套用上面第三條 將 false 轉換為 數值
// 這個輸出 0
console.log(Number(false))
// 包裝類型與 基本類型 == 先將包裝類型通過 valueOf toString 轉換為基本類型
// 輸出 ""
console.log([].toString())
// 套用第2條, 將空字符串轉換為數值、
// 輸出 0
console.log(Number(""))
// 所以
console.log(0 == 0)
第四行代碼
// 輸出 1console.log(true + false)
兩個基本類型相加,如果其中一方是字符,則將其他的轉換為字符相加,否則將類型轉換為Number,然后相加, Number(true) 是1, Number(false)是0, 所以結果是 1
本文中的所有題目首發于公眾號【前端有的玩】,小編每天都會整理一道兩道面試題,然后推送給所有的朋友,關注小編,每天帶你去刷面試題,不想當咸魚,想要換工作,還在猶豫什么,關注 === 大廠offer。
結語
不要吹滅你的靈感和你的想象力; 不要成為你的模型的奴隸。——文森特?梵高
總結
以上是生活随笔為你收集整理的前端面试instanceof_一起回归一下每日一题这些经典面试题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python3.7安装pip问题_pyt
- 下一篇: python中不具备np_Python中