Function.prototype.myCall = function (context, ...args) {
if (typeof this !== 'function') {
throw new TypeError('not a function');
}
if (context === undefined || context === null) {
// 如果传入的上下文对象是undefined或null的话,则直接使用window对象作为上下文对象
context = window;
} else {
context = Object(context);
}
var specialPrototype = Symbol('specialPrototype'); // 给上下文对象添加的临时属性
context[specialPrototype] = this; // 将this函数添加到上下文对象上
var result = context[specialPrototype](...args); // 调用上下文对象上的方法获取执行结果
delete context[specialPrototype]; // 删除上下文对象上添加的临时属性
return result; // 返回函数执行结果
}
二、手写bind函数
Function.prototype.myBind = function (thisArg) {
if (typeof this !== 'function') {
throw new TypeError('not a function');
}
var that = this;
var args = Array.prototype.slice.call(arguments, 1);
var fn = function () {}
var fnBound = function () {
const _this = this instanceof fn ? this : thisArg;
const newArgs = args.concat(Array.prototype.slice.call(arguments));
return that.apply(_this, newArgs);
}
if (this.prototype) {
fn.prototype = this.prototype;
}
fnBound.prototype = new fn();
fnBound.prototype.constructor = this;
return fnBound;
};
三、手写实现new功能的函数
function myNew(fn, ...args) {
// 创建一个空的对象,将实例化对象的原型指向构造函数的原型对象
const instance = Object.create(fn.prototype);
// 将构造函数的this指向实例化对象
const res = fn.apply(instance, args);
// 判断返回值,如果函数返回值为基本数据类型时, 则new出的对象依然是创建出的对象
return res instanceof Object ? res : instance;
}
四、手写reduce函数
Array.prototype.myReduce = function (fn, initialValue) {
// 判断调用对象是否为数组
if (Object.prototype.toString.call(this) !== '[object Array]') {
throw new TypeError('not a array');
}
// 判断调用数组是否为空数组
if (this.length === 0) {
throw new TypeError('empty array');
}
// 判断传入的第一个参数是否为函数
if (typeof fn !== 'function') {
throw new TypeError(`${fn} is not a function`);
}
// 回调函数参数初始化
var sourceArray = this;
var result, currentValue, currentIndex;
if (initialValue !== undefined) {
result = initialValue;
currentIndex = 0;
} else {
result = sourceArray[0];
currentIndex = 1;
}
// 开始循环
while (currentIndex < sourceArray.length) {
if (Object.prototype.hasOwnProperty.call(sourceArray, currentIndex)) {
currentValue = sourceArray[currentIndex];
result = fn(result, currentValue, currentIndex, sourceArray);
}
currentIndex++;
}
// 返回结果
return result;
}
五、手写防抖函数
function debounce(fn, delay=300) {
if (typeof fn !== 'function') {
throw new TypeError(`${fn} is not a function`);
}
let timer = null;
return (...args) => {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
}
}
六、手写节流函数
function throttle(fn, duration=500) {
if (typeof fn !== 'function') {
throw new TypeError(`${fn} is not a function`);
}
let lastTime = new Date().getTime();le
return (...args) => {
const now = new Date().getTime();
if (now - lastTime >= duration) {
fn.apply(this, args);
lastTime = now;
}
}
}