前端面试题系列文章:
- 【1】备战前端实习面试之HTML篇
- 【2】备战前端实习面试之CSS篇
- 【3】备战前端实习面试之JavaScript篇
- 【4】备战前端实习面试之React篇
- 【5】备战前端实习面试之Vue篇
- 【6】备战前端实习面试之Node.js篇
- 【7】备战前端实习面试之浏览器篇
- 【8】备战前端实习面试之性能优化篇
- 【9】备战前端实习面试之计算机网络篇
- 【10】备战前端实习面试之手写代码篇
- 【11】备战前端实习面试之代码输出结果篇
手写代码
手写 Object.create
作用:将传入的对象作为原型
function _create(obj) {
function F();
F.prototype = obj;
return new F();
}
手写 instanceof 方法
instanceof 运算符用于判断构造函数的 prototype
属性是否出现在对象的原型链中的任何位置。
function _instanceof(left, right) {
if (!((typeof left === 'function' || (typeof left === 'Object' && left)) && typeof right === 'function')) {
throw new Error('传入的参数不符合规范');
}
let left = Object.getPrototypeOf(left);
const right = right.prototype;
while (true) {
if (!left) return false;
if (left === right) return true;
// 如果没有找到,就继续从其原型上找,Object.getPrototypeOf 方法用来获取指定对象的原型
left = Object.getPrototypeOf(left);
}
}
手写 call
Function.prototype._call = function(context, ...arg) {
context = context || window;
if (typeof context !== 'object') {
context = Object.create(null);
}
const fn = Symbol('fn');
context[fn] = this;
const result = context[fn](...arg);
delete context[fn];
return result;
}
手写 apply
Function.prototype._apply = function(context, arg) {
context = context || window;
if (typeof context !== 'object') {
context = Object.create(null);
}
const fn = Symbol('fn');
context[fn] = this;
}
手写 bind
Function.prototype._bind = function(context, ...arg) {
let obj = null;
let constructor = Array.prototype.shift.call(arguments);
let result = null;
if (typeof constructor !== 'function') {
return;
}
obj = Object.create(constructor.prototype);
result = constructor.apply(obj, arguments);
let flag = result && (typeof result === 'object' || typeof result == 'function')
return flag ? result : obj;
}
JS 实现洋葱模型
一维数组转树桩
function arrayToTree(arr) {
const res = [];
const arrMap = {};
for (const item of arr) {
arrMap[item.id] = {...item, children: []};
}
for (const item of arr) {
const id = item.id;
const parent = item.parent;
const treeItem = itemMap[id];
if (!parent) {
res.push()
}
}
}
手写防抖、节流
防抖
function debounce(fn, wait) { let timeout = null; return function () { let _this = this; let args = arguments; if (timeout) { clearTimeout(timeout); timeout = null; } timeout = setTimeout(() => { fn.apply(_this, args); }, wait); } }
节流
方式一:使用时间戳
function throttle(fn, wait) {
let previous = 0;
return function () {
let now = Date.now();
const _this = this;
const args = arguments;
if (now - previous > wait) {
fn.apply(_this, args);
previous = now;
}
}
}
方式二:使用定时器
function throttle (fn, wait) {
let timeout = null;
return function () {
const _this = this;
const args = arguemnts;
if (!timeout) {
timeout = setTimeout(() => {
fn.apply(_this, args);
timeout = null;
}, wait);
}
}
}
函数柯里化
function curry(fn, args) {
let len = fn.length;
args = args || [];
return function() {
let subArgs = args.slice(0);
for (let i = 0; i < )
}
}
编程题:有一个数组 idArr ,长度是 100; 现在要调用一个接口 fetch 去查询每个数组元素 id
对应的 name;要求要分批调用,每批最多只能查询 10 个,以此实现一个 batch 函数;
进阶1:怎么判断批量操作是否都成功了,还是有的失败了;
进阶2:实现能找到查询失败的数据,并重新批量发接口重试
const idArr = [{
id: '1',
}, {
id: '2',
}, {
id: '100',
}];
fetch: (params: {id: string}[]) => Promise<{id: string; name: string}[]>
const batch = (idArr: {id: string}[]): Promise<{id: string; name: string}[]>[] => {
};