Javascript手写代码题
本文整理了面试中常见的 Javascript 手写代码题,例如函数科里化,call
,apply
,bind
,节流函数,防抖函数,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
指向,但是不同于 apply
和 call
方法,它返回的是一个函数,而不是一个结果
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;
}