前端面试手写题目总结

1、冒泡排序


// 1、冒泡排序--大的向后排小的向前排
function bubbleSortFn(arr) {
    for (let i =  arr.length - 1 ; i >= 1; i--) {
        for(let j = 0; j < i; j++) {
            if (arr[j] > arr[j + 1]) {
                let temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
    return arr;
}
console.log('bubbleSortFn:', bubbleSortFn([12, 33, 1, 3, 49, -1, 88]))

2、选择排序


// 2、选择排序--选择出小的向前排
function selectSortFn(arr) {
    for(let i = 0; i < arr.length; i++) {
        // 默认第一次最小的值下标
        let min = i;
        // 向后比较
        for (let j = i + 1; j < arr.length; j++) {
            if (arr[j] < arr[min]) {
                // 如果有更小的
                min = j;
            }
        };
        // 把小的换前面来
        let temp = arr[i];
        arr[i] = arr[min];
        arr[min] = temp;
    }
    return arr;
}
console.log('selectSortFn:', selectSortFn([12, 33, 1, 3,2, 49, -1, 88]))

3、插入排序

// 3、插入排序--局部有序
function insertSortFn(arr) {
    // 默认第一个是有序的
    for(let i = 1; i < arr.length; i++) {
        let temp = arr[i];
        let j = i;
        while(arr[j - 1] > temp && j > 0) {
            arr[j] = arr[j - 1];
            j--;
        }
        arr[j] = temp;
    }
    return arr;
}
console.log('insertSortFn:', insertSortFn([12, 33, 1, 3,2, 49, -1, 88]))


4、二分法查找

// 4、二分法查找
function twoFindFn(arr, target) {
    arr.sort((a, b) => a - b);
    let left = 0;
    let right = arr.length - 1;
    while(left <= right) {
        let middle = Math.floor((left + right) / 2);
        if (target < arr[middle]) {
            // 在左边
            right = middle - 1;
        } else if(target > arr[middle]) {
            // 在右边
            left = middle + 1;
        } else {
            return middle;
        }
    }
    return -1;
}
console.log('twoFindFn:', twoFindFn([12, 33, 1, 3,2, 49, -1, 88], 1))

5、实现一个计数器


// 5、实现一个计数器
function sendCountFn(n) {
    return function() {
        return n++;
    }
}
let afterCountFn = sendCountFn(3);
console.log(afterCountFn())
console.log(afterCountFn())

6、获取 URL 参数

// 6、获取 URL 参数
function getSearchParams() {
    let paramsObj = {};
    let search = new URLSearchParams(location.search);
    for(let [key, value] of search.entries()) {
        // console.log(key, value)
        paramsObj[key] = value;
    };
    return paramsObj;
}


function getSearchParams2() {
    let resObj = {};
    let searchStr = location.search.substring(1);
    let searchStrArr = searchStr.split('&');
    searchStrArr.forEach(item => {
        const [key, value] = item.split('=');
        resObj[key] = value;
    });
    return resObj;
}


7、手写 new 的执行过程


 // 7.手写 new 的执行过程
 function myNew(Constructor, ...args) {
    // 1创建对象
    let obj = {};
    // 2设置原型链
    obj.__proto__ = Constructor.prototype;
    // 前两步也可以用Object.create代替
    // let obj = Object.create(Constructor.prototype);

    // 3调用并复制实例属性方法
    obj.apply(Constructor, args);
    return obj;
 }


8、手写实现 Object.create()


// 8. 手写实现 Object.create()
function myCreate(prototype) {
    // console.log(Object.prototype.toString.call(prototype));
    if (Object.prototype.toString.call(prototype) != '[object Object]') {
        throw 'prototype is not a Object';
    }
    // 创建纯净的构造函数
    function F() {};
    F.prototype = prototype;
    return new F();
}
// myCreate(null)


9、instanceof实现


// 9.instanceof实现
function myInstanceof(instance, constructor) {
    // 判断实例__proto__是否等于构造函数原型链上的原型对象
    while(instance) {
        if (instance.__proto__ == constructor.prototype) return true;
        instance = instance.__proto__;
    }
    return false;
}
console.log('myInstanceof:', myInstanceof('wsw', Array))


10、实现红黄绿循环打印


// 10.js 实现红黄绿循环打印
const task = (color, time) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve();
            console.log(color)
        }, time);
    })
}

async function taskRunner() {
    await task('red', 1000);
    await task('green', 2000);
    await task('yellow', 3000);
    taskRunner();
}
// taskRunner();

11、用 promise 如何实现异步加载图片


// 11.用 promise 如何实现异步加载图片
function importImageFn(src) {
    return new Promise((resolve, reject) => {
        let imgObj = new Image();
        imgObj.src = src;
        imgObj.onload = function() {
            resolve();
        };
        imgObj.onerror = function() {
            reject();
        }
    })
}

13、实现数组的 push、filter、map 方法

// 13.实现数组的 push、filter、map 方法
 Array.prototype.mypush = function(...args) {
    let arr = this;
    let length = arr.length;
    for(let i = 0; i < args.length; i++) {
        arr[length + i] = args[i];
    }
    return arr;
 }
let myarr = [];
// myarr.mypush(1);
// myarr.mypush(11);
myarr.mypush('1', '2', '3');
console.log('myPush:', myarr);


Array.prototype.myfilter = function(callback) {
    let arr = this;
    let length = this.length;
    let newArr = [];
    for(let i = 0; i < length; i++) {
        if (callback && callback(arr[i], i , arr)) {
            newArr.push(arr[i])
        }
    }
    return newArr;
}
console.log('myfilter:', [1, 2, 3, 4].myfilter(item => item >= 3));

Array.prototype.mymap = function(callback) {
    let arr = this;
    let length = this.length;
    let newArr = [];
    for(let i = 0; i < length; i++) {
        newArr.push(callback(arr[i], i ,arr));
    }
    return newArr;
}

console.log('mymap:', [1, 2, 3, 4].mymap(item => item + 3));

14、使用 setTimeout 实现 setInterval


// 14.使用 setTimeout 实现 setInterval
function mysetInterval(callback, time) {
    let timer = null;
    let isStop = false;
    const repeat = () => {
        if (isStop) return;
        callback();
        timer = setTimeout(repeat, time)
    }
    repeat();
    return {
        stop: function() {
            clearTimeout(timer);
            timer = null;
            isStop = true;
        }
    }
}
let count = 0;
let stopRes;
stopRes = mysetInterval(() => {
    count++;
    console.log('mysetInterval....', count)
    if (count === 5) { // 停止条件:当 count 达到 5 时停止
        stopRes.stop();
    }
}, 3000);


15、手写 bind

// 15.手写 bind-- 改变this指向但不执行
Function.prototype.mybind = function(obj, ...args) {
    let self = this;
    return function(...arguments) {
        self.apply(obj, [...args, ...arguments]);
    }
}

16、实现 jsonp

// 16.实现 jsonp
function myJsonp(api, callbackName, success, fail) {
    let scriptEle = document.createElement('script');
    scriptEle.src = `${api}?callbackName=${callbackName}`;
    document.body.appendChild(scriptEle);
    window[callbackName] = function(response) {
        success && success(response);
        document.body.removeChild(scriptEle);
    }
    
}

17、手写一个深度比较 isEqual

// 17.手写一个深度比较 isEqual
function isEqual(obj1, obj2) {
    if (typeof obj1 != 'object' || typeof obj2 != 'object') {
        return obj1 === obj2;
    };
    if (obj1 === obj2) return true;
    let keys1 = Object.keys(obj1);
    let keys2 = Object.keys(obj2);
    if (keys1.length !== keys2.length) return false;
    for (const iterator of keys1) {
        let res = isEqual(obj1[iterator], obj2[iterator]);
        if (!res) return false;
    };
    return true;
}
console.log('isEqual:', isEqual({name: {age: 10}}, {name: {age: 10}}))

18、手写深拷贝

// 18.手写深拷贝
function deepClone(obj) {
    if (typeof obj != 'object' || obj == null) return;
    let target = Array.isArray(obj) ? [] : {};
    for (key in obj) {
        if (Object.hasOwnProperty.call(obj, key)) {
            if (typeof obj[key] == 'object') {
                deepClone(obj[key])
            } else {
                target[key] = obj[key];
            }
        }
    }
    return target;
};

19、手写数组去除重复

// 19.手写数组去除重复

function removeRep(arr) {
    return [...new Set(arr)];
}

function removeRep2(arr) {
    let resArr = [];
    arr.forEach(item => {
        if (!resArr.includes(item)) {
            resArr.push(item);
        }
    });
    return resArr;
}


20、大数相加

// 20.大数相加
function bigNumAdd(num1, num2) {
    let sum = '';
    let addNum = '';
    let f = 0;
    // 补齐
    let maxLen = Math.max(num1.length, num2.length);
    num1 = num1.padStart(maxLen, '0');
    num2 = num2.padStart(maxLen, '0');
    for(let i = maxLen - 1; i >= 0; i--) {
        addNum = parseInt(num1[i]) + parseInt(num2[i]) + f;
        f = Math.floor(addNum / 10);
        sum = addNum % 10 + sum;
    };
    if (f == 1) {
        sum = '1' + sum;
    }
    return sum;
}

21、节流函数

// 21.节流函数
function throttle(fn, delay) {
    let content = this;
    let timer = null;
    let isFirst = true;
    return (...arguments) => {
        if (isFirst) {
            fn.apply(content, arguments);
            isFirst = false;
            return;
        }
        if (timer) return;
        timer = setTimeout(() => {
            fn.apply(content, arguments);
            timer = null;
        }, delay);
    }
}

22、防抖函数

// 22. 防抖函数
function debund(fn, delay) {
    const content = this;
    let timer = null;
    let isFirst = true;
    return (...args) => {
        if (isFirst) {
            fn.apply(content, args);
            isFirst = false;
            return;
        }
        if (timer) clearTimeout(timer);
        timer = setTimeout(() => {
            fn.apply(content, args);
            timer = null;
        }, delay);
    }
}

23、设计一个图片懒加载 SDK

 // 23、设计一个图片懒加载 SDK

    const throttle = (fn, delay) => {
        let timer = null
        return function (...args) {
          if (!timer) {
            setTimeout(() => {
              fn.apply(this, args)
              timer = null
            }, delay)
          }
        }
      }
      
      const lazyLoadImages = () => {
        const images = document.querySelectorAll('img[data-src]')
        images.forEach((img) => {
          const rect = img.getBoundingClientRect()
          if (rect.top < window.innerHeight) {
            img.src = img.dataSet.src
            img.removeAttribute('data-src')
          }
        })
      }
      
      const throttledLazyLoad = throttle(lazyLoadImages, 100)
      
      window.addEventListener('scroll', throttledLazyLoad)

24、用正则实现trim() 清除字符串两端空格


 // 24、用正则实现trim() 清除字符串两端空格
 String.prototype.mytrim = function() {
    let str = this;
    return str.replace(/(^\s)|(\s$)/g, '');
}
console.log(' xsxsxsxs  '.mytrim())

25、简单写一个webpack配置文件

 // 25、简单写一个webpack配置文件
 // webpack.config.js
module.exports = {
    mode: 'development',
    entry: './src/index.js',
    output: {
        filename: 'build.js',
        path: resolve('../dist/')
    },
    modules: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
            {
                test: /\.html$/,
                use: ['html-loader']
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './index.html'
        }),
    ],
    devServer: {
        port: 3000,
        ...
    }
}

26、react自定义 Hook useCountdown

/**
 * 请通过 React Hooks API 实现一个具有倒计时功能的自定义 Hook useCountdown,
 * 要求可以使组件每秒自动更新倒计时。
 * 当超过倒计时截止时间 targetDate 时,变成正计时(返回的 expired 为 false)
 *
 * @param {Date} targetDate 倒计时截止时间
 */
// function useCountdown(targetDate) {
//   // 你的代码实现...

//   // 返回的数据结构示例
//   return {
//     expired: false, // 是否已超期
//     days: 0, // 剩余或已超过天数(整数),无上限
//     hours: 0, // 剩余或已超过小时(整数),0~23
//     minutes: 0, // 剩余或已超过分钟数(整数),0~59
//     seconds: 0, // 剩余或已超过秒数(整数),0~59
//   };
// }
function useCountdown(targetDate) {  
  const [countdown, setCountdown] = useState({  
    expired: false,  
    days: 0,  
    hours: 0,  
    minutes: 0,  
    seconds: 0,  
  });  
  
  useEffect(() => {
    const intervalId = setInterval(() => {
      const now = new Date();  
      const distance = targetDate - now;
      if (distance <= 0) {  
        // 超过截止时间,开始正计时  
        const expiredDistance = now - targetDate;  
        const expiredDays = Math.ceil(expiredDistance / (1000 * 60 * 60 * 24));  
        const expiredHours = Math.ceil((expiredDistance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));  
        const expiredMinutes = Math.ceil((expiredDistance % (1000 * 60 * 60)) / (1000 * 60));  
        const expiredSeconds = Math.ceil((expiredDistance % (1000 * 60)) / 1000);
        setCountdown({  
          expired: true,  
          days: expiredDays,  
          hours: expiredHours,  
          minutes: expiredMinutes,  
          seconds: expiredSeconds,  
        });  
      } else {  
        // 倒计时  
        const days = Math.ceil(distance / (1000 * 60 * 60 * 24));  
        const hours = Math.ceil((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));  
        const minutes = Math.ceil((distance % (1000 * 60 * 60)) / (1000 * 60));  
        const seconds = Math.ceil((distance % (1000 * 60)) / 1000);  
        setCountdown({  
          expired: false,  
          days,  
          hours,  
          minutes,  
          seconds,  
        });  
      }  
    }, 1000); // 每秒更新一次
  }, [targetDate]); // 当targetDate变化时,重新计算倒计时  
  return countdown;  
}

27、实现一下call和apply方法

Function.prototype.myCall = function(context, ...args) {
    if (typeof this !== 'function') {
        throw Error('this is not Fcnction');
    };
    let contentObj = context || window;
    context.fn = this;
    // 执行方法
    let result = context.fn(...args);
    delete context.fn;
    return result;
};

Function.prototype.myApply = function(content, ...agrs) {
    if (typeof this !=  'function') {
        throw Error('this is not function');
    };
    let execObj = content || window;
    execObj.fn = this;
    let result = execObj.fn(agrs);
    delete execObj.fn;
    return result;
}

28、 写一个前端图片压缩的工具方法

// 写一个前端图片压缩的工具方法
 function compressImg(url, qulidy = 0.7, name = '') {
    let imgType = url.split('.').pop() || 'jpeg';
    // 获取图片的宽高
    let imgObj = new Image();
    imgObj.src = url;
    imgObj.onload = function() {
         console.dir(imgObj);
        // 创建canvas
        let canvasEle = document.createElement('canvas');
        canvasEle.width = imgObj.width;
        canvasEle.height = imgObj.height;
        let canvasCont = canvasEle.getContext('2d');
        canvasCont.drawImage(imgObj, 0, 0, imgObj.width, imgObj.height);
        let canvasDataUrl = canvasEle.toDataURL(`image/${imgType}`, qulidy);
        console.log(canvasDataUrl)
        // 通过a标签下载
        let aEle = document.createElement('a');
        aEle.href = canvasDataUrl;
        aEle.download = (name || 'test') + '.' + imgType ;
        document.body.appendChild(aEle);
        aEle.click();
        document.body.remove(aEle);
    }
 }

 compressImg('http://127.0.0.1:8080/123.jpeg', 0.1, 'testimg12')

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LuckyCola2023

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值