1)防抖节流
// 节流,一定时间内只执行第一个触发
const throttle = (func, wait = 500) => {
let lastTime = 0;
return function (...args) {
let now = new Date();
if (now - lastTime > wait) {
lastTime = now;
func.apply(this,args);
}
};
};
// 防抖,一定时间只执行最近一次触发
const debounce = (func, wait = 500) => {
let timer = 0;
return function (...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this,args);
}, wait);
};
};
2) 排序算法
// 冒泡排序
function bubbleSort(arr) {
// 思路就是遍历数组,每次和右边的数字比大小,比之大就交换位置
let length = arr.length;
for (let i = 0; i <= length - 2; i++) {
for (let j = i + 1; j <= length - 1; j++) {
if (arr[i] > arr[j]) {
[arr[i], arr[j]] = [arr[j], arr[i]];
}
}
}
return arr;
}
// console.log(bubbleSort(arr));
// 快速排序,利用二分法
// 会占用额外空间,不是最优解
function quickSort(arr) {
// 1.找一个标志位
// 2.数组切成两半
// 3.对left和right,递归使用相同条件
// 终止条件
if (arr.length <= 1) return arr;
let flag = arr.shift();
let left = [];
let right = [];
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
if (arr[i] < flag) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat(flag, quickSort(right));
}
// 原地快排,不会占用额外空间
let quickSort2 = (arr, low = 0, high = arr.length - 1) => {
let left = low;
let right = high;
let flag = arr[left];
if (low > high) return arr;
while (left < right) {
while (left < right && arr[right] > flag) {
right--;
}
arr[left] = arr[right];
while (left < right && arr[left] < flag) {
left++;
}
arr[right] = arr[left];
}
arr[left] = flag;
quickSort2(arr, low, left - 1);
quickSort2(arr, left + 1, high);
return arr;
};
3)柯里化函数
let curry = (fn) => {
return function curriedFn(...args) {
console.log('形参个数', fn.length);
if (args.length < fn.length) {
return function () {
return curriedFn(...args.concat(...arguments));
};
}
return fn(...args);
};
};
4)call
// es3写法
Function.prototype.es3call = function (context) {
var content = context || window; //判断是否传递上下文,没有的话默认为全局作用域
content.fn = this; //保存原来函数
var args = [];
// argument是一个伪数组,因为第一个参数是content,所以下标从1开始
for (var i = 1; i < arguments.length; i++) {
// 为啥不是直接 args.push(arguments[i]);
// 因为那样如果参数传递字符串,类似这样传递
// add.es3call(obj, '你好', '我好')
// 导致eval在执行时,表达式变成了eval("obj.fn(你好,我好,)")
// 对于eval而言就像传递了没加引号的字符串,所以就会报错
// 而通过args.push('arguments[' + i + ']') 就可以先不解析
// 遍历完的args长这样 ["arguments[1]","arguments[2]","arguments[3]"]
// 当执行eval时,arguments[1]此时确实是作为一个变量存在,所以不会报错,于是被eval解析成了一个真正的字符传递给了函数
args.push('arguments[' + i + ']');
}
// 利用eval函数,执行js代码
// 此处使用eval是因为,数组不能直接作为参数传递给fn,而eval再执行时,会把变量转换成字符串,隐性执行了arr.toString()
var result = eval('content.fn(' + args + ')');
// 后面fn不需要了,删除
delete content.fn;
return result;
};
// es6写法
Function.prototype.es6call = function (context) {
const content = context || window;
content.fn = this;
const args = [];
for (let i = 1; i < arguments.length; i++) {
args.push(`arguments[${i}]`);
}
const result = content.fn(...args);
delete content.fn;
return result;
};
5)apply
// apply实现
// es3实现
Function.prototype.es3Apply = function (context, arr) {
var content = context || window;
content.fn = this;
var result;
if (!arr) {
result = content.fn();
} else {
var args = [];
for (var i = 0; i < arr.length; i++) {
args.push('arr[' + i + ']');
}
result = eval('content.fn(' + args + ')');
}
// 后面fn不需要了,删除
delete content.fn;
return result;
};
// es6实现
Function.prototype.es6Apply = function (context, arr) {
var content = context || window;
content.fn = this;
var result;
if (!arr) {
result = content.fn();
} else {
if (!(arr instanceof Array)) throw new Error('参数必须是数组');
result = content.fn(...arr);
}
// 后面fn不需要了,删除
delete content.fn;
return result;
};
6)bind
// bind实现
Function.prototype.es6bind = function (context) {
const content = context || window;
const _this = this;
const args = Array.prototype.slice.call(arguments, 1);
return function () {
return _this.apply(content, args.concat(...arguments));
};
};