做网站需要会语言吗,营销策划的流程,医生做兼职有什么网站吗,营销型企业网站的功能前言
想想几年前一个月随便投出去一天至少3面试一个月排满面试的场景对于现在已经灭绝了#xff0c;基本只有外包和驻场有回应#xff0c;今年很多人都只能猥琐发育#xff0c;市场上不仅岗位变少#xff0c;money也少了很多。目前环境的不景气#xff0c;面试难度也增加…前言
想想几年前一个月随便投出去一天至少3面试一个月排满面试的场景对于现在已经灭绝了基本只有外包和驻场有回应今年很多人都只能猥琐发育市场上不仅岗位变少money也少了很多。目前环境的不景气面试难度也增加了很多在这样的大环境下也只能不断提升提升自己时刻警惕被优化的风险。最近刚好复习到手写面试题的基础分享分享给大家伙。
手写实现节流函数
function throttle(func, delay) {let timeoutId; // 用于存储定时器的IDlet lastExecutedTime 0; // 上次执行的时间戳// 返回一个新的函数作为节流函数return function (...args) {const currentTime Date.now(); // 当前时间戳// 计算距离上次执行的时间间隔const elapsedTime currentTime - lastExecutedTime;// 如果距离上次执行的时间间隔大于等于延迟时间则执行函数if (elapsedTime delay) {func.apply(this, args);lastExecutedTime currentTime; // 更新上次执行的时间戳} else {// 如果距离上次执行的时间间隔小于延迟时间则设置定时器延迟执行函数clearTimeout(timeoutId);timeoutId setTimeout(() {func.apply(this, args);lastExecutedTime Date.now(); // 更新上次执行的时间戳}, delay - elapsedTime);}};
}
该实现中throttle 函数接收两个参数func 是要进行节流处理的函数delay 是时间间隔表示在间隔时间内只能执行一次函数。
节流函数返回一个新的函数作为节流后的函数。每次调用节流后的函数时它会记录当前时间戳并计算距离上次执行的时间间隔。
如果距离上次执行的时间间隔大于等于延迟时间则立即执行目标函数并更新上次执行的时间戳。
如果距离上次执行的时间间隔小于延迟时间则设置一个定时器在延迟时间减去时间间隔后执行目标函数并更新上次执行的时间戳。
这样可以确保目标函数在一定时间间隔内只能执行一次。
示例演示如何使用节流函数
function handleResize() {console.log(Resize event throttled);
}const throttledResize throttle(handleResize, 200);window.addEventListener(resize, throttledResize);
在示例中我们定义了一个 handleResize 函数并使用 throttle 函数对其进行节流处理。然后我们将节流后的函数 throttledResize 添加到 resize 事件的监听器中。这样当窗口大小调整时handleResize 函数只会在每 200 毫秒执行一次从而减少了函数的执行频率。
手写实现防抖函数
function debounce(func, delay) {let timeoutId; // 用于存储定时器的ID// 返回一个新的函数作为防抖函数return function (...args) {// 如果已经设置了定时器则清除它if (timeoutId) {clearTimeout(timeoutId);}// 设置新的定时器延迟执行目标函数timeoutId setTimeout(() {func.apply(this, args);}, delay);};
}该实现中debounce 函数接收两个参数func 是要进行防抖处理的函数delay 是延迟时间表示在最后一次触发后等待多久执行函数。
防抖函数返回一个新的函数作为防抖后的函数。每次调用防抖后的函数时它会判断是否已经设置了定时器。如果已经设置了定时器则清除之前的定时器以防止函数执行。然后设置一个新的定时器延迟执行目标函数。
当最后一次调用防抖后的函数后如果在延迟时间内没有再次调用则定时器会触发执行目标函数 func。这样可以确保目标函数只在最后一次调用后延迟一段时间执行。
示例演示如何使用防抖函数
function handleScroll() {console.log(Scroll event debounced);
}const debouncedScroll debounce(handleScroll, 200);window.addEventListener(scroll, debouncedScroll);
在示例中我们定义了一个 handleScroll 函数并使用 debounce 函数对其进行防抖处理。然后我们将防抖后的函数 debouncedScroll 添加到 scroll 事件的监听器中。这样当页面滚动时handleScroll 函数只会在最后一次滚动后的 200 毫秒延迟执行从而减少了函数的执行次数。
函数柯里化的实现
function curry(fn) {// 定义内部函数用于递归调用function curried(...args) {// 如果传入的参数数量大于或等于原始函数的参数数量则直接调用原始函数if (args.length fn.length) {return fn(...args);} else {// 如果参数数量不足则返回一个新的函数继续等待接收剩余的参数return function (...moreArgs) {return curried(...args, ...moreArgs);};}}return curried; // 返回柯里化后的函数
}
手写实现new操作符
// 自定义new操作符函数模拟实现new操作符的功能
function myNew(constructorFn, ...args) {// 创建一个空对象并将其原型设置为构造函数的原型const obj Object.create(constructorFn.prototype);// 调用构造函数并将this绑定到新创建的对象上const result constructorFn.apply(obj, args);// 如果构造函数返回一个对象则返回该对象否则返回新创建的对象if (typeof result object result ! null) {return result;}return obj;
}// 示例构造函数
function Person(name, age) {this.name name;this.age age;
}Person.prototype.sayHello function() {console.log(Hello, my name is ${this.name} and Im ${this.age} years old.);
};// 使用示例
const john myNew(Person, John, 25);
john.sayHello(); // Output: Hello, my name is John and Im 25 years old.
手写实现instanceof
// 自定义instanceof操作符函数模拟实现instanceof操作符的功能
function myInstanceOf(obj, constructorFn) {// 获取构造函数的原型对象const prototype constructorFn.prototype;// 判断对象的原型链中是否存在构造函数的原型while (obj ! null) {if (obj.__proto__ prototype) {return true;}obj obj.__proto__;}return false;
}// 示例构造函数
function Person(name, age) {this.name name;this.age age;
}// 使用示例
const john new Person(John, 25);
console.log(myInstanceOf(john, Person)); // Output: true
console.log(myInstanceOf(john, Object)); // Output: true
console.log(myInstanceOf(john, Array)); // Output: false
手写实现Promise
// 自定义Promise类模拟实现Promise的基本功能
class MyPromise {constructor(executor) {// Promise的三个状态pending、fulfilled、rejectedthis.state pending;this.value undefined;this.reason undefined;// 用于存储异步操作的回调函数this.onFulfilledCallbacks [];this.onRejectedCallbacks [];// 执行executor函数try {executor(this.resolve.bind(this), this.reject.bind(this));} catch (error) {this.reject(error);}}// 解决Promise状态变为fulfilledresolve(value) {if (this.state pending) {this.state fulfilled;this.value value;// 执行所有已注册的fulfilled回调函数this.onFulfilledCallbacks.forEach(callback callback(this.value));}}// 拒绝Promise状态变为rejectedreject(reason) {if (this.state pending) {this.state rejected;this.reason reason;// 执行所有已注册的rejected回调函数this.onRejectedCallbacks.forEach(callback callback(this.reason));}}// 注册Promise的回调函数then(onFulfilled, onRejected) {if (this.state fulfilled) {onFulfilled(this.value);} else if (this.state rejected) {onRejected(this.reason);} else if (this.state pending) {// 异步操作时将回调函数存储起来待异步操作完成后执行this.onFulfilledCallbacks.push(onFulfilled);this.onRejectedCallbacks.push(onRejected);}// 返回新的Promise对象实现链式调用return this;}
}// 使用示例
const promise new MyPromise((resolve, reject) {setTimeout(() {resolve(Hello, Promise!);}, 2000);
});promise.then(value {console.log(value); // Output: Hello, Promise!
});
promise.all()的实现
Promise.all 方法用于接收一个 Promise 数组并在所有 Promise 都成功解析时返回一个包含所有 Promise 结果的新 Promise。如果任何一个 Promise 失败则返回的 Promise 将立即被拒绝并带有失败的原因。
function promiseAll(promises) {return new Promise((resolve, reject) {const results []; // 用于保存每个Promise的结果let completedPromises 0; // 已经完成的Promise数量// 遍历传入的Promise数组for (let i 0; i promises.length; i) {// 对每个Promise进行处理promises[i].then((result) {// 如果Promise成功解决则将结果保存在相应的位置results[i] result;completedPromises;// 当所有Promise都完成时返回结果if (completedPromises promises.length) {resolve(results);}}).catch((error) {// 如果有一个Promise被拒绝则立即返回拒绝的结果reject(error);});}// 处理空Promise数组的情况if (promises.length 0) {resolve(results);}});
}
promise.race的实现
Promise.race方法接收一个包含多个Promise的可迭代对象如数组并返回一个新的Promise。这个新的Promise将与第一个解决resolve或拒绝reject的Promise具有相同的解决值或拒绝原因。
function promiseRace(promises) {return new Promise((resolve, reject) {// 遍历传入的Promise数组for (const promise of promises) {// 对每个Promise进行处理promise.then((result) {// 如果有一个Promise解决则使用resolve解决新的Promiseresolve(result);}).catch((error) {// 如果有一个Promise被拒绝则使用reject拒绝新的Promisereject(error);});}});
}
Promise.allSettled的实现
Promise.allSettled 方法接收一个包含多个 Promise 的可迭代对象如数组并返回一个新的 Promise。这个新的 Promise 在所有传入的 Promise 都解决或拒绝后才会被解决并返回一个包含每个 Promise 结果的对象数组。对象数组中的每个对象都表示对应的 Promise 结果包含 status 字段表示 Promise 的状态“fulfilled” 表示解决“rejected” 表示拒绝以及对应的 value 或 reason 字段表示解决值或拒绝原因。
function promiseAllSettled(promises) {const settledPromises [];// 遍历传入的 Promise 数组for (const promise of promises) {// 对每个 Promise 进行处理settledPromises.push(Promise.resolve(promise).then((value) ({status: fulfilled,value: value,})).catch((reason) ({status: rejected,reason: reason,})));}return Promise.all(settledPromises);
}
手写实现apply函数
// 自定义apply函数模拟实现apply的功能
function myApply(fn, context, args) {if (typeof fn ! function) {throw new TypeError(fn must be a function);}// 创建唯一的属性名用于防止上下文对象属性的覆盖const uniqueKey Symbol();// 将函数fn作为上下文对象的一个属性context[uniqueKey] fn;// 调用函数fn并传入参数数组const result context[uniqueKey](...args);// 删除添加的属性delete context[uniqueKey];return result;
}// 使用示例
function greet(greeting) {return ${greeting}, ${this.name}!;
}const person { name: John };
const greeting myApply(greet, person, [Hello]);
console.log(greeting); // Output: Hello, John!
手写实现call函数
// 自定义call函数模拟实现call的功能
function myCall(fn, context, ...args) {if (typeof fn ! function) {throw new TypeError(fn must be a function);}// 创建唯一的属性名用于防止上下文对象属性的覆盖const uniqueKey Symbol();// 将函数fn作为上下文对象的一个属性context[uniqueKey] fn;// 调用函数fn并传入参数列表const result context[uniqueKey](...args);// 删除添加的属性delete context[uniqueKey];return result;
}// 使用示例
function greet(greeting) {return ${greeting}, ${this.name}!;
}const person { name: John };
const greeting myCall(greet, person, Hello);
console.log(greeting); // Output: Hello, John!
手写实现bind函数
// 自定义bind函数模拟实现bind的功能
function myBind(fn, context, ...args) {if (typeof fn ! function) {throw new TypeError(fn must be a function);}return function (...newArgs) {// 将bind时传入的参数和调用时传入的参数合并const allArgs [...args, ...newArgs];// 调用函数fn并绑定上下文和参数列表return fn.apply(context, allArgs);};
}// 使用示例
function greet(greeting) {return ${greeting}, ${this.name}!;
}const person { name: John };
const greetPerson myBind(greet, person, Hello);
const greeting greetPerson();
console.log(greeting); // Output: Hello, John!
手写实现深拷贝函数
function deepClone(obj, hash new WeakMap()) {if (obj null) return obj; // 如果是null或者undefined我就不进行拷贝操作if (obj instanceof Date) return new Date(obj);if (obj instanceof RegExp) return new RegExp(obj);// 可能是对象或者普通的值 如果是函数的话是不需要深拷贝if (typeof obj ! object) return obj;// 是对象的话就要进行深拷贝if (hash.get(obj)) return hash.get(obj);let cloneObj new obj.constructor();// 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身hash.set(obj, cloneObj);for (let key in obj) {if (obj.hasOwnProperty(key)) {// 实现一个递归拷贝cloneObj[key] deepClone(obj[key], hash);}}return cloneObj;
}
let obj { name: 1, address: { x: 100 } };
obj.o obj; // 对象存在循环引用的情况
let d deepClone(obj);
obj.address.x 200;
console.log(d);
手写实现数组的find方法
// 自定义数组的find方法模拟实现数组的find方法
Array.prototype.myFind function(callback, thisArg) {// 判断调用myFind方法的对象是否为数组if (!Array.isArray(this)) {throw new TypeError(myFind called on non-array object);}// 遍历数组并调用回调函数查找满足条件的元素for (let i 0; i this.length; i) {// 调用回调函数并传入当前元素、索引和原数组作为参数const satisfiesCondition callback.call(thisArg, this[i], i, this);// 如果回调函数返回true则返回当前元素if (satisfiesCondition) {return this[i];}}// 如果没有满足条件的元素则返回undefinedreturn undefined;
};// 使用示例
const numbers [1, 2, 3, 4, 5];// 使用自定义的myFind方法查找数组中第一个偶数
const evenNumber numbers.myFind(function(num) {return num % 2 0;
});console.log(evenNumber); // Output: 2
手写实现数组的every方法
// 自定义数组的every方法模拟实现数组的every方法
Array.prototype.myEvery function(callback, thisArg) {// 判断调用myEvery方法的对象是否为数组if (!Array.isArray(this)) {throw new TypeError(myEvery called on non-array object);}// 遍历数组并调用回调函数判断是否满足条件for (let i 0; i this.length; i) {// 调用回调函数并传入当前元素、索引和原数组作为参数const satisfiesCondition callback.call(thisArg, this[i], i, this);// 如果有一个元素不满足条件则返回falseif (!satisfiesCondition) {return false;}}// 如果所有元素都满足条件则返回truereturn true;
};// 使用示例
const numbers [1, 2, 3, 4, 5];// 使用自定义的myEvery方法判断数组是否所有元素都是奇数
const isAllOdd numbers.myEvery(function(num) {return num % 2 ! 0;
});console.log(isAllOdd); // Output: false
手写实现数组的some方法
// 自定义数组的some方法模拟实现数组的some方法
Array.prototype.mySome function(callback, thisArg) {// 判断调用mySome方法的对象是否为数组if (!Array.isArray(this)) {throw new TypeError(mySome called on non-array object);}// 遍历数组并调用回调函数判断是否满足条件for (let i 0; i this.length; i) {// 调用回调函数并传入当前元素、索引和原数组作为参数const satisfiesCondition callback.call(thisArg, this[i], i, this);// 如果回调函数返回true则返回trueif (satisfiesCondition) {return true;}}// 如果没有满足条件的元素则返回falsereturn false;
};// 使用示例
const numbers [1, 2, 3, 4, 5];// 使用自定义的mySome方法判断数组是否存在偶数
const hasEvenNumber numbers.mySome(function(num) {return num % 2 0;
});console.log(hasEvenNumber); // Output: true
手写实现数组的forEach方法
// 自定义数组的forEach方法模拟实现数组的forEach方法
Array.prototype.myForEach function(callback, thisArg) {// 判断调用myForEach方法的对象是否为数组if (!Array.isArray(this)) {throw new TypeError(myForEach called on non-array object);}// 遍历数组并调用回调函数对每个元素进行操作for (let i 0; i this.length; i) {// 调用回调函数并传入当前元素、索引和原数组作为参数callback.call(thisArg, this[i], i, this);}
};// 使用示例
const numbers [1, 2, 3, 4, 5];// 使用自定义的myForEach方法对数组进行遍历
numbers.myForEach(function(num) {console.log(num);
});// Output:
// 1
// 2
// 3
// 4
// 5
手写实现数组的reduce方法
// 自定义数组的reduce方法模拟实现数组的reduce方法
Array.prototype.myReduce function(callback, initialValue) {// 判断调用myReduce方法的对象是否为数组if (!Array.isArray(this)) {throw new TypeError(myReduce called on non-array object);}// 判断数组是否为空if (this.length 0 initialValue undefined) {throw new TypeError(Reduce of empty array with no initial value);}let accumulator initialValue ! undefined ? initialValue : this[0];// 遍历数组并调用回调函数对每个元素进行聚合操作for (let i initialValue ! undefined ? 0 : 1; i this.length; i) {// 调用回调函数并传入累加器、当前元素、索引和原数组作为参数accumulator callback(accumulator, this[i], i, this);}// 返回聚合结果return accumulator;
};// 使用示例
const numbers [1, 2, 3, 4, 5];// 使用自定义的myReduce方法对数组进行求和
const sum numbers.myReduce(function(acc, num) {return acc num;
}, 0);console.log(sum); // Output: 15
手写实现数组的filter方法
// 自定义数组的filter方法模拟实现数组的filter方法
Array.prototype.myFilter function(callback, thisArg) {// 判断调用myFilter方法的对象是否为数组if (!Array.isArray(this)) {throw new TypeError(myFilter called on non-array object);}// 创建一个新的空数组用于存储过滤后的结果const filteredArray [];// 遍历数组并调用回调函数对每个元素进行过滤for (let i 0; i this.length; i) {// 调用回调函数并传入当前元素、索引和原数组作为参数const shouldKeep callback.call(thisArg, this[i], i, this);// 如果回调函数返回true则将当前元素添加到新数组中if (shouldKeep) {filteredArray.push(this[i]);}}// 返回过滤后的新数组return filteredArray;
};// 使用示例
const numbers [1, 2, 3, 4, 5];// 使用自定义的myFilter方法对数组进行过滤
const evenNumbers numbers.myFilter(function(num) {return num % 2 0;
});console.log(evenNumbers); // Output: [2, 4]
手写实现数组的map方法
// 自定义数组的map方法模拟实现数组的map方法
Array.prototype.myMap function(callback, thisArg) {// 判断调用myMap方法的对象是否为数组if (!Array.isArray(this)) {throw new TypeError(myMap called on non-array object);}// 创建一个新的空数组用于存储映射后的结果const mappedArray [];// 遍历数组并调用回调函数对每个元素进行映射for (let i 0; i this.length; i) {// 调用回调函数并传入当前元素、索引和原数组作为参数const mappedValue callback.call(thisArg, this[i], i, this);// 将映射后的值添加到新数组中mappedArray.push(mappedValue);}// 返回映射后的新数组return mappedArray;
};// 使用示例
const numbers [1, 2, 3, 4, 5];// 使用自定义的myMap方法对数组进行映射
const doubledNumbers numbers.myMap(function(num) {return num * 2;
});console.log(doubledNumbers); // Output: [2, 4, 6, 8, 10]
在这个示例中我们手写实现了数组的map方法。我们在Array.prototype对象上添加了一个名为myMap的方法。该方法接受一个回调函数作为参数用于对数组的每个元素进行映射操作。我们遍历数组的每个元素并调用回调函数将当前元素、索引和原数组作为参数传递给回调函数。然后我们将映射后的值添加到一个新的数组中并最后返回该数组。
结尾
希望有帮助到的朋友可以帮忙点点赞点点关注是对我最大的支持同时最近需要跳槽面试的同学需要高频面试宝典大全也可以私信我或者关注公众号【前端嚣张农民】回复-999
同时后面也会更新性能优化相关、vue3的实战项目、nodejs的知识点、包括最近开始使用react项目了之前一直使用的都是vue和angular也会更新最近写的项目用nextjs框架喜欢的可以点点关注不迷路大家一起学习