前端手写面试题合集
创始人
2024-03-24 04:17:43
0

实现ES6的extends

function B(name){this.name = name;
};
function A(name,age){//1.将A的原型指向BObject.setPrototypeOf(A,B);//2.用A的实例作为this调用B,得到继承B之后的实例,这一步相当于调用superObject.getPrototypeOf(A).call(this, name)//3.将A原有的属性添加到新实例上this.age = age; //4.返回新实例对象return this;
};
var a = new A('poetry',22);
console.log(a);

实现apply方法

思路: 利用this的上下文特性。apply其实就是改一下参数的问题

Function.prototype.myApply = function(context = window, args) {// this-->func  context--> obj  args--> 传递过来的参数// 在context上加一个唯一值不影响context上的属性let key = Symbol('key')context[key] = this; // context为调用的上下文,this此处为函数,将这个函数作为context的方法// let args = [...arguments].slice(1)   //第一个参数为obj所以删除,伪数组转为数组let result = context[key](...args); // 这里和call传参不一样// 清除定义的this 不删除会导致context属性越来越多delete context[key]; // 返回结果return result;
}
// 使用
function f(a,b){console.log(a,b)console.log(this.name)
}
let obj={name:'张三'
}
f.myApply(obj,[1,2])  //arguments[1]

实现redux-thunk

redux-thunk 可以利用 redux 中间件让 redux 支持异步的 action

// 如果 action 是个函数,就调用这个函数
// 如果 action 不是函数,就传给下一个中间件
// 发现 action 是函数就调用
const thunk = ({ dispatch, getState }) => (next) => (action) => {if (typeof action === 'function') {return action(dispatch, getState);}return next(action);
};
export default thunk

实现一个padStart()或padEnd()的polyfil

String.prototype.padStartString.prototype.padEndES8中新增的方法,允许将空字符串或其他字符串添加到原始字符串的开头或结尾。我们先看下使用语法:

String.padStart(targetLength,[padString])

用法:

'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(5, 'ab') // 'xabab'// 1. 若是输入的目标长度小于字符串原本的长度则返回字符串本身
'xxx'.padStart(2, 's') // 'xxx'// 2. 第二个参数的默认值为 " ",长度是为1的
// 3. 而此参数可能是个不确定长度的字符串,若是要填充的内容达到了目标长度,则将不要的部分截取
'xxx'.padStart(5, 'sss') // ssxxx// 4. 可用来处理日期、金额格式化问题
'12'.padStart(10, 'YYYY-MM-DD') // "YYYY-MM-12"
'09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12"

polyfill实现:

String.prototype.myPadStart = function (targetLen, padString = " ") {if (!targetLen) {throw new Error('请输入需要填充到的长度');}let originStr = String(this); // 获取到调用的字符串, 因为this原本是String{},所以需要用String转为字符串let originLen = originStr.length; // 调用的字符串原本的长度if (originLen >= targetLen) return originStr; // 若是 原本 > 目标 则返回原本字符串let diffNum = targetLen - originLen; // 10 - 6 // 差值for (let i = 0; i < diffNum; i++) { // 要添加几个成员for (let j = 0; j < padString.length; j++) { // 输入的padString的长度可能不为1if (originStr.length === targetLen) break; // 判断每一次添加之后是否到了目标长度originStr = `${padString[j]}${originStr}`;}if (originStr.length === targetLen) break;}return originStr;
}
console.log('xxx'.myPadStart(16))
console.log('xxx'.padStart(16))

还是比较简单的,而padEnd的实现和它一样,只需要把第二层for循环里的${padString[j]}${orignStr}换下位置就可以了。

reduce用法汇总

语法

array.reduce(function(total, currentValue, currentIndex, arr), initialValue);
/*total: 必需。初始值, 或者计算结束后的返回值。currentValue: 必需。当前元素。currentIndex: 可选。当前元素的索引;                     arr: 可选。当前元素所属的数组对象。initialValue: 可选。传递给函数的初始值,相当于total的初始值。
*/

reduceRight() 该方法用法与reduce()其实是相同的,只是遍历的顺序相反,它是从数组的最后一项开始,向前遍历到第一项

1. 数组求和

const arr = [12, 34, 23];
const sum = arr.reduce((total, num) => total + num);// 设定初始值求和
const arr = [12, 34, 23];
const sum = arr.reduce((total, num) => total + num, 10);  // 以10为初始值求和// 对象数组求和
var result = [{ subject: 'math', score: 88 },{ subject: 'chinese', score: 95 },{ subject: 'english', score: 80 }
];
const sum = result.reduce((accumulator, cur) => accumulator + cur.score, 0); 
const sum = result.reduce((accumulator, cur) => accumulator + cur.score, -10);  // 总分扣除10分

2. 数组最大值

const a = [23,123,342,12];
const max = a.reduce((pre,next)=>pre>cur?pre:cur,0); // 342

3. 数组转对象

var streams = [{name: '技术', id: 1}, {name: '设计', id: 2}];
var obj = streams.reduce((accumulator, cur) => {accumulator[cur.id] = cur; return accumulator;}, {});

4. 扁平一个二维数组

var arr = [[1, 2, 8], [3, 4, 9], [5, 6, 10]];
var res = arr.reduce((x, y) => x.concat(y), []);

5. 数组去重

实现的基本原理如下:① 初始化一个空数组
② 将需要去重处理的数组中的第1项在初始化数组中查找,如果找不到(空数组中肯定找不到),就将该项添加到初始化数组中
③ 将需要去重处理的数组中的第2项在初始化数组中查找,如果找不到,就将该项继续添加到初始化数组中
④ ……
⑤ 将需要去重处理的数组中的第n项在初始化数组中查找,如果找不到,就将该项继续添加到初始化数组中
⑥ 将这个初始化数组返回
var newArr = arr.reduce(function (prev, cur) {prev.indexOf(cur) === -1 && prev.push(cur);return prev;
},[]);

6. 对象数组去重

const dedup = (data, getKey = () => { }) => {const dateMap = data.reduce((pre, cur) => {const key = getKey(cur)if (!pre[key]) {pre[key] = cur}return pre}, {})return Object.values(dateMap)
}

7. 求字符串中字母出现的次数

const str = 'sfhjasfjgfasjuwqrqadqeiqsajsdaiwqdaklldflas-cmxzmnha';const res = str.split('').reduce((pre,next)=>{pre[next] ? pre[next]++ : pre[next] = 1return pre 
},{})
// 结果
-: 1
a: 8
c: 1
d: 4
e: 1
f: 4
g: 1
h: 2
i: 2
j: 4
k: 1
l: 3
m: 2
n: 1
q: 5
r: 1
s: 6
u: 1
w: 2
x: 1
z: 1

8. compose函数

redux compose 源码实现

function compose(...funs) {if (funs.length === 0) {return arg => arg;}if (funs.length === 1) {return funs[0];}return funs.reduce((a, b) => (...arg) => a(b(...arg)))
}

实现一个 sleep 函数,比如 sleep(1000) 意味着等待1000毫秒

// 使用 promise来实现 sleep
const sleep = (time) => {return new Promise(resolve => setTimeout(resolve, time))
}sleep(1000).then(() => {// 这里写你的骚操作
})

参考 前端进阶面试题详细解答

实现new的过程

new操作符做了这些事:

  • 创建一个全新的对象
  • 这个对象的__proto__要指向构造函数的原型prototype
  • 执行构造函数,使用 call/apply 改变 this 的指向
  • 返回值为object类型则作为new方法的返回值返回,否则返回上述全新对象
function myNew(fn, ...args) {// 基于原型链 创建一个新对象let newObj = Object.create(fn.prototype);// 添加属性到新对象上 并获取obj函数的结果let res = fn.apply(newObj, args); // 改变this指向// 如果执行结果有返回值并且是一个对象, 返回执行的结果, 否则, 返回新创建的对象return typeof res === 'object' ? res: newObj;
}
// 用法
function Person(name, age) {this.name = name;this.age = age;
}
Person.prototype.say = function() {console.log(this.age);
};
let p1 = myNew(Person, "poety", 18);
console.log(p1.name);
console.log(p1);
p1.say();

二分查找

function search(arr, target, start, end) {let targetIndex = -1;let mid = Math.floor((start + end) / 2);if (arr[mid] === target) {targetIndex = mid;return targetIndex;}if (start >= end) {return targetIndex;}if (arr[mid] < target) {return search(arr, target, mid + 1, end);} else {return search(arr, target, start, mid - 1);}
}// const dataArr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// const position = search(dataArr, 6, 0, dataArr.length - 1);
// if (position !== -1) {
//   console.log(`目标元素在数组中的位置:${position}`);
// } else {
//   console.log("目标元素不在数组中");
// }

实现findIndex方法

var users = [{id: 1, name: '张三'},{id: 2, name: '张三'},{id: 3, name: '张三'},{id: 4, name: '张三'}
]Array.prototype.myFindIndex = function (callback) {// var callback = function (item, index) { return item.id === 4 }for (var i = 0; i < this.length; i++) {if (callback(this[i], i)) {// 这里返回return i}}
}var ret = users.myFind(function (item, index) {return item.id === 2
})console.log(ret)

实现JSONP方法

利用