跳到主内容

Javascript手写代码题

本文整理了面试中常见的 Javascript 手写代码题,例如函数科里化,callapplybind,节流函数,防抖函数,new 的实现原理等等

函数科里化

函数科里化是函数式编程一个重要的思想,是把一个函数的多个参数转为接收单一参数的技术,例如 f(a, b, c) 转为 f(a)(b)(c) 或者 f(a)(b, c),举个例子

function sum(a, b) {
return a + b;
}

let curriedSum = curry(sum);
curriedSum(1)(3); // 4

我们来实现一个科里化函数

/**
* @param {Function} fn 函数
* @param {Number} arity 参数个数
* @param {Array} args 初始化参数
*/
const curry = (fn, arity = fn.length, ...args) =>
arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args);

验证

const curriedSum = curry(sum);
curriedSum(1)(3); // 4

实现 call 函数

call() 方法改变 this 指向特定的值,传入的是一个逗号隔开的多个参数

Function.prototype.myCall = function (ctx, ...args) {
ctx = ctx || window;
ctx.fn = this;
const res = ctx.fn(...args);
delete ctx.fn;
return res;
};

实现 apply 函数

apply() 方法改变 this 指向特定的值,传入的是一个参数组成的数组

Function.prototype.myApply = function (ctx, args) {
ctx = ctx || window;
ctx.fn = this;
const res = ctx.fn(...args);
delete ctx.fn;
return res;
};

实现 bind 函数

bind() 也可以改变 this 指向,但是不同于 applycall 方法,它返回的是一个函数,而不是一个结果

Function.prototype.myBind = function (ctx, ...args) {
const fnToBind = this; // 需要绑定的函数
const fn = function () {}; // 新建一个构造函数,用来实例化
const fnBound = function () {
const _this = this instanceof fn ? this : ctx;
return fnToBind.apply(_this, [...args, ...arguments]);
};
fn.prototype = fnToBind.prototype; // fn继承fnToBind的原型
fnBound.prototype = new fn(); // fnBound方法的原型链指向fn的实例
return fnBound;
};

实现防抖函数

防抖功能就是实现函数多次触发的情况下,只执行最后一次

使用场景:输入下拉远程搜索,避免多次触发

function debounce(fn, delay) {
let timer = null;
return function (args) {
timer && clearTimeout(timer);
timer = setTimeout(fn, args);
};
}

实现节流函数

节流函数就是在高频触发的,控制触发的频率,在指定的间隔内只执行一次

使用场景:onscroll,onresize,减少触发的频率

function throttle(fn, delay) {
let start = +new Date();
return function (args) {
let now = +new Date();
let diff = now - start;
if (diff >= delay) {
fn(...args);
start = now;
}
};
}

new 的实现原理

function myNew(constructor, ...args) {
// 创建一个对象,o.__proto__ = constructor.prototype
const o = Object.create(constructor.prototype);
// 执行构造函数
const result = constructor.apply(o, args);
// 判断结果是对象,则返回,否则返回新对象
return result && (typeof result === "function" || typeof result === "object") ? result : o;
}