前言
一些手写题练习记录
一、手写call bind
call() : 传入的参数按序传入即可,返回执行结果
apply(): 传入的参数需要是数组形式,返回执行结果
bind():入参同call,返回一个待执行的函数
// 手写call
function myCall(fn, obj, ...args) {
if(obj === null || obj === undefined) {
return fn(...args)
}
obj.fn = fn;
let result = obj.fn(...args);
delete obj.fn;
return result;
}
// 手写bind
function myBind(fn, obj, ...args) {
return function(...args1) {
obj.call(fn, obj, ...args, ...args1)
}
}
二、手写new
// 手写new
function myNew (fn, ...args) {
let obj = {};
let result = fn.apply(obj, ...args);
if(result instanceof obj) {
return result
}
obj.__proto__ = fn.prototype;
return obj;
}
三、节流防抖
节流:立即执行,然后计算当下与上一次有效执行的时间间隔大于等于delay时执行。常用:滚动条。
防抖:使用settimeout,第一次不执行,本次执行与上一次有效操作之间间隔大于等于指定时间长度时执行。常用:搜索输入框匹配;按钮点击事件。
// 节流
function throttle(callback, delay) {
let start = 0;
return function(event) {
let now = Date.now();
if(now - start > delay) {
callback(event.target, event);
start = now;
}
}
}
// 防抖
function debounce(callback, delay) {
return function(event){
if(event.timeoutId) {
clearTimeout(event.timeoutId)
}
event.timeoutId = setTimeout(()=>{
callback(event.target, event);
event.timeoutId = null;
},delay)
}
}
四、数组扁平化
// 数组扁平化
let arr = [1,2,4,[4,3,5,6[5,6,7]],[4,5,5,[4,6,8]],4,7,9];
function flatten(arrs) {
return arrs.reduce((pre, item) => {
if(Array.isArray(item) && item.some(cItem => Array.isArray(cItem))){
return pre.concat(flatten(item))
}else{
return pre.concat(item)
}
},[])
}
function flatten2(arrs) {
while(arrs.some(item => Array.isArray(item))){
arrs = [].concat(...arrs)
}
return arrs;
}
五、冒泡排序
// 冒泡排序
function newSort(list) {
for (let i = 0; i<list.length; i++) {
for(let j = 0; j<i; j++) {
if(list[j] > list[j+1]) {
[list[i], list[j]] = [list[j], list[i]]
}
}
}
}
六、实现数组方法
// forEach
Array.prototype.myForeach = function (callback){
for(let i = 0; i< this.length; i++) {
callback(this[i], i, this)
}
}
// map
Array.prototype.myMap = function(callback) {
let arr = [];
for(let i = 0; i< this.length; i++) {
arr.push( callback(this[i], i, this))
}
return arr;
}
// some
Array.prototype.mySome = function(callback) {
for(let i = 0; i< this.length; i++) {
if(callback(this[i])) {
return true;
}
}
return false;
}
// every
Array.prototype.myEvery = function(callback) {
for (let i = 0; i<this.length; i++) {
if(!callback(this[i])){
return false;
}
}
return true;
}
// filter
Array.prototype.myFilter = function(callback) {
let arr = [];
for(let i = 0; i< this.length; i++){
if(callback(this[i])) {
arr.push(this[i])
}
}
return arr;
}
// repeat 方法, 每间隔一定时间执行相同函数
async function sleep(fn, wait, ...args) {
return new Promise(resolve => {
setTimeout(()=>{
fn.apply(...args);
resolve();
},wait)
})
}
function repeat(fn, times, wait) {
return async function() {
for(let i =0; i<times; i++) {
await sleep(fn, wait, arguments)
}
}
}
七、柯里化
// 柯里化
function currlys (fn, args) {
// 参数的个数大于等于函数数量
return args.length >= fn.length
// 直接执行
? fn(...args)
// 递归执行,继续进行柯里化,把所有参数都传进去
: (..._args) => currlys(fn, ...args, ..._args)
}