上岸半个月,开始回来学习写博客,先看了之前自己写的面经,决定先把一些常见的题目总结出来
(以下皆为面试bat字节时遇到的题目)
这里直接上代码,测试有问题的欢迎各位在评论区指出,注释看不懂其中代码也欢迎提出问题
实现promise的API
Promise.all
- 参数:数组
- 返回:一个promise对象
- 功能:该方法接受一个数组作为参数,数组成员为Promise对象,若不是Promise对象,则先使用Promise.resolve方法变为对象。而事实上,数组参数中的每个值都会经过Promise.resolve方法的过滤。若数组中所有Promise对象的状态都变成已成功,则该方法返回的Promise对象的状态也变为已成功;若数组中有一个Promise对象状态变为已失败,则第一个变为已失败的对象的返回值传递给最后返回的Promise对象,该对象状态也变为已失败。
Promise._all = function(promises){
return new Promise((resolve,reject)=>{
// 将可遍历的类型转为数组形式
promises = Array.from(promises)
// 若数组长度为0,则直接resolve([])
if(promises.length === 0){
resolve([])
}else{
// 使用一个变量count来计算当前已完成的promise
let count = 0
for(let i=0;i<promises.length;i++){
Promise.resolve(promises[i]).then(val=>{
promises[i] = val
// 若完成的promise数量和数组长度一致,说明全部完成,则返回处理好的数组
if(++count === promises.length){
resolve([promises])
}
}).catch(err=>{
reject(err)
})
}
}
})
}
Promise.race
- 参数:数组
- 返回:一个promise对象
- 功能:该方法与Promise.finally一样,都传入一个数组做为参数,但是返回的promise对象的状态,由数组中最先发生状态改变的promise决定,如果传入一个空数组,状态永远不会发生改变
Promise._race = function(promises){
promises = Array.from(promises)
return new Promise((resolve,reject)=>{
promises.forEach(p=>{
Promise.resolve(p).then(val=>{
resolve(val)
}).catch(err=>{
reject(err)
})
})
})
}
Promise.finally
- 参数:一个回调方法
- 返回:一个promise对象
-功能:Promise.finally执行的时候,不管原来的状态变为resolve或是变为reject,都会去执行传入的回调方法
Promise._finally = function(callback){
return this.then(val=>{
return Promise.resolve(callback()).then(()=>{
return val
})
},err=>{
return Promise.resolve(callback()).then(()=>{
throw err
})
})
}
深拷贝
const deepClone =(initalObj) =>
{
if (typeof initalObj !== 'object') {//如果是基本类型直接返回值
return initalObj
}
const obj = Array.isArray(initalObj)?[]:{};//可能是对象或者数组
for (const key in initalObj) {
if (typeof initalObj[key] === 'object') {//对于对象元素,deepclone
//递归返回新的对象
obj[key] = deepClone(initalObj[key]);
} else if (typeof initalObj[key] === 'function') {//对于函数,用bind拷贝
//返回新函数
obj[key] = initalObj[key].bind(obj);
} else {
//基本类型直接返回
obj[key] = initalObj[key];
}
}
return obj;
}
实现一个bind
Function.prototype.bind2 = function(context,...rest){
if(typeof this !== "function"){
throw new TypeError("Uncaught TypeError: Bind must be called on a function") // 不是函数时抛出错误
}
var self = this // 保存这个方法
var Fn = function () {} // 使用一个空函数做为继承的中间函数
var fBound = function (...inRest){
self.apply(this instanceof Fn ? this : context, rest.concat(inRest)) // 这里的处理是当使用new运算符时,this指向被改变,我们就不能使用context做为this了,new运算符优先级高于bind
}
// 本来可以通过fBound.prototype = self.prototype实现原型链绑定
// 但是这也导致了当我们改变fBound.prototype时,因为和self也就是原函数使用了同一个引用,所以会修改原函数的prototype
Fn.prototype = self.prototype
fBound.prototype = new Fn()
return fBound
}
实现一个new
function _new(c,...args){
if(typeof c !=="function"){
throw new TypeError(`${c} is not a constructor`) // 判断不是函数时抛出错误
}
let obj = Object.create(c.prototype) // 实现继承
let res = c.call(obj,...args) // 绑定this
return typeof res === "object"||typeof res === "function"?res:obj // 若返回的是对象,则返回该对象,否则返回实例
}
大数相加
var bigAdd = function(n1, n2) {
n1 += ""
n2 += ""
let i1 = n1.length-1
let i2 = n2.length-1
let flag = 0
let res = ""
while (i1 >= 0 || i2 >= 0 || flag) {
let num1 = Number(n1[i1--]) || 0
let num2 = Number(n2[i2--]) || 0
let sum = num1 + num2 + flag
flag = 0
if(sum >= 10){
flag = 1
sum -= 10
}
res = sum + res
}
return res
}
数组中出现的数字次数大于2/n的数
function find(arr){
let value = arr[0],
count = 1
for(let i=1;i<arr.length;i++){
if(count==0){
count++
value = arr[i]
}else if(value === arr[i]){
count++
}else{
count--
}
}
return value
}
排序算法
冒泡
function bubbleSort(arr) {
for (let i = 0; i < arr.length - 1; i++) {
for (let j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
let temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
return arr
}
插入
function insertSort(arr) {
for (let i = 0; i < arr.length; i++) {
for (let j = i; j > 0; j--) {
if (arr[j] < arr[j - 1]) {
let temp = arr[j]
arr[j] = arr[j - 1]
arr[j - 1] = temp
}
}
}
return arr
}
选择
function chooseSort(arr) {
let maxIndex, maxNum, temp
for (let i = 0; i < arr.length - 1; i++) {
maxIndex = 0
maxNum = arr[0]
for (let j = 0; j < arr.length - i; j++) {
if (arr[j] > maxNum) {
maxIndex = j
maxNum = arr[j]
}
}
temp = arr[arr.length - i - 1]
arr[maxIndex] = temp
arr[arr.length - i - 1] = maxNum
}
return arr
}
快速
function fastSort(arr) {
if (arr.length <= 1) {
return arr
} else {
let sign = arr[0],
low = 0,
high = arr.length - 1
while (low < high) {
while (arr[low + 1] < sign && low < high) {
arr[low] = arr[low + 1]
low++
}
if (low !== high) {
let temp = arr[low + 1]
arr[low + 1] = arr[high]
arr[high] = temp
high--
}
}
arr[low] = sign
return [...fastSort(arr.slice(0, low)), sign, ...fastSort(arr.slice(low + 1))]
}
}
归并
function merageSort(arr) {
let len = arr.length
if (len == 1) {
return arr
}
let mid = Math.floor(len / 2)
return merage(merageSort(arr.slice(0, mid)), merageSort(arr.slice(mid)))
}
function merage(left, right) {
let result = []
let li = 0,
ri = 0,
llen = left.length,
rlen = right.length
while (li < llen && ri < rlen) {
if (left[li] < right[ri]) {
result.push(left[li])
li++
} else {
result.push(right[ri])
ri++
}
}
return li < llen ?
result.concat(left.slice(li)) :
result.concat(right.slice(ri))
}
希尔
function hillSort(arr) {
let gap = Math.floor(arr.length / 2)
while (gap >= 1) {
for (let i = gap; i < arr.length; i++) {
let j, temp = arr[i]
for (j = i - gap; j >= 0 && arr[j] > temp; j -= gap) {
arr[j + gap] = arr[j]
}
arr[j + gap] = temp
}
gap = Math.floor(gap / 2)
}
return arr
}
最长递增子序列
function find(arr){
let len = arr.length
let countArr = new Array(len).fill(1)
let max = 1
for(let i = 1;i < len; i++){
for(let j = 0;j<i;j++){
if(arr[j]<arr[i]){
countArr[i] = countArr[i]>countArr[j]+1?countArr[i]:countArr[j]+1
}
}
max = max>countArr[i]?max:countArr[i]
}
return max
}