一.函数柯里化
const add = function add(x) {
return function (y) {
return x + y
}
}
const add1 = add(1)
add1(2) === 3
add1(20) === 21
二.手写闭包
function a(){
var n = 0;
function add(){
n++;
console.log(n);
}
return add;
}
var a1 = a(); //注意,函数名只是一个标识(指向函数的指针),而()才是执行函数;
a1(); //1
a1(); //2 第二次调用n变量还在内存中
三.手写bind函数
function bind_1(asThis, ...args) {
const fn = this; // 这里的 this 就是调用 bind 的函数 func
return function (...args2) {
return fn.apply(asThis, ...args, ...args2);
};
}
四.手写call函数
Function.prototype.myCall = function (context) {
var context = context || window
// 给 context 添加一个属性
// getValue.call(a, 'yck', '24') => a.fn = getValue
context.fn = this
// 将 context 后面的参数取出来
var args = [...arguments].slice(1)
// getValue.call(a, 'yck', '24') => a.fn('yck', '24')
var result = context.fn(...args)
// 删除 fn
delete context.fn
return result
}
五.手写apply函数
Function.prototype.myApply = function (context) {
var context = context || window
context.fn = this
var result
// 需要判断是否存储第二个参数
// 如果存在,就将第二个参数展开
if (arguments[1]) {
result = context.fn(...arguments[1])
} else {
result = context.fn()
}
delete context.fn
return result
}
六.数组扁平化
const arr = [1, [2, [3, [4, 5]]], 6];
方式一:flat
const res1 = arr.flat(Infinity);
方式二:函数递归
const res5 = [];
const fn = arr => {
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
fn(arr[i]);
} else {
res5.push(arr[i]);
}
}
}
fn(arr);
七.数组去重
const arr = [1, 1, '1', 17, true, true, false, false, 'true', 'a', {}, {}];
方式一:利用set
const res1 = Array.from(new Set(arr));
方式二:利用indexOf
const unique2 = arr => {
const res = [];
for (let i = 0; i < arr.length; i++) {
if (res.indexOf(arr[i]) === -1) res.push(arr[i]);
}
return res;
}
方式三:利用filter
const unique4 = arr => {
return arr.filter((item, index) => {
return arr.indexOf(item) === index;
});
}
八.防抖
触发高频时间后n秒内函数只会执行一次,如果n秒内高频时间再次触发,则重新计算时间。
const debounce = (fn, time) => {
let timeout = null;
return function() {
clearTimeout(timeout)
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, time);
}
};
九.节流
高频时间触发,但n秒内只会执行一次,所以节流会稀释函数的执行频率。
const throttle = (fn, time) => {
let flag = true;
return function() {
if (!flag) return;
flag = false;
setTimeout(() => {
fn.apply(this, arguments);
flag = true;
}, time);
}
}
十.深拷贝(面试够用版)
浅拷贝+递归 (只考虑了普通的 object和 array两种数据类型)
function cloneDeep(target,map = new WeakMap()) {
if(typeOf taret ==='object'){
let cloneTarget = Array.isArray(target) ? [] : {};
if(map.get(target)) {
return target;
}
map.set(target, cloneTarget);
for(const key in target){
cloneTarget[key] = cloneDeep(target[key], map);
}
return cloneTarget
}else{
return target
}
}
本文详细介绍了前端面试中常见的手写题目,包括函数的柯里化、闭包、bind、call、apply的实现,以及数组的扁平化、去重、防抖和节流等实用技巧,旨在帮助求职者掌握核心技能。
555

被折叠的 条评论
为什么被折叠?



