面试必问:手撕代码系列(二)

简介: 面试必问:手撕代码系列(二)

手撕代码系列(二)


手写函数柯里化 curring

/**
 * 函数柯里化 curring
 * @param {Function}
 * @return 视具体方法而定
 *
 * @logic
 *  1.创建一个参数数组 args
 *  2.创建一个函数,接收参数列表
 *  3.函数判断参数数组是否有值
 *  4.如果有值,则往 args 中进行 push 操作,否则就是没有参数了,则直接进行调用
 *  5.调用后,将 args 参数数组清空
 *  6.返回参数数组
 */
const curring = fn => {
    let args = [];
    return function temp(...rest) {
        if (rest.length) {
            args.push(...rest);
            return temp;
        } else {
            let result = fn.apply(this, args);
            args = [];
            return result;
        }
    }
}
// test:
const add = (...args) => {
    return args.reduce((prev, next) => prev + next, 0);
}
console.log(curring(add)(1)(2)(3)(4)(5)());  // 15
console.log(curring(add)(1)(2)(3)(4,5)()); // 15
console.log(curring(add)(1,2)(3,4,5)()); // 15
console.log(curring(add)(1)(2,3,4,5)()); // 15

手写数组乱序方法 shuffle

/**
 * 随机洗牌
 * @param {Array} arr 要被打乱的数组
 * @returns 打乱后的元素
 *
 * @logic
 *  1.  从还没处理的数组中,从 [0, array.length] 之间取一个随机数 random number
 *  2.  从剩下的 array.length 中把第 random 元素取出来放在新数组 result 中
 *  3.  删除原数组中第 random 个元素
 *  4.  重复2,3步骤直到所有元素取完
 *  5.  最终返回新数组即可
 */
const shuffle = source => {
    let arr = Array.from(source);
    let result = [];
    while (arr.length) {
        let random = (Math.random() * arr.length) | 0;
        // let random = Math.floor(Math.random() * arr.length);
        // let random = (Math.random() * arr.length) >> 0;
        // let random = (Math.random() * arr.length) << 0;
        // let random = (Math.random() * arr.length) >>> 0;
        // let random = ~~(Math.random() * arr.length);
        result.push(arr[random]);
        arr.splice(random, 1)
    }
    return result;
}
// test:
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
console.log("shuffle(numbers) ------->", shuffle(numbers));
// shuffle(numbers) -------> [
//    9,  1, 17,  6, 10, 12, 18,
//   19, 20,  8, 13,  2, 11, 15,
//    7,  4, 16, 14,  5,  3
// ]

手写解析 URL Params 方法 getUrlParams

/**
 * 解析 URL Params getUrlParams
 * @param {String} urlStr
 * @return {Object} 参数对象
 */
// 方法一:
const getUrlParams = url => {
    // 解析url,获取参数部分
    let urlStr = url.split('?')[1];
    // 判断是否有 hash 值
    let newStr = '';
    // 去重 hash 值逻辑
    if (urlStr.includes('#')) {
        newStr = urlStr.split('#')[0];
    }
    // 参数重置化
    let res = new URLSearchParams(newStr);
    // Object.fromEntries() 方法将 key value 数组形式转换为对象;
    /**
    demo:
        let obj = {
            a: 1,
            b: 2
        }
        console.log(Object.fromEntries(Object.entries(obj)));
     */
    return Object.fromEntries(res.entries())
}
// 方法二:
const getUrlParams = url => {
    let urlParams = new URL(url);
    return Object.fromEntries(urlParams.searchParams.entries());
}
// test:
let tempUrl =
    "https://www.baidu.com:80/temp/src/index.html?name=John&sex=14#hash=title";
console.log("getUrlParams(tempUrl) ------->", getUrlParams(tempUrl));
// getUrlParams(tempUrl) -------> { name: 'John', sex: '14' }

手写数组扁平化 myFlat

/**
 * 数组扁平化 myFlat
 * @param {Array} source 需要扁平化的数组
 * @returns 扁平化后的新数组
 */
// 方法一:
const myFlat = source => {
    // 结果数组
    let result = [];
    // 遍历
    for (let i = 0; i < source.length; i++){
        // 数组元素
        let item = source[i];
        // 判断当前项是否为数组,若是数组递归执行
        if (Array.isArray(item)) {
            // result.concat(myFlat(item)) 使用之前的列表(result)拼接当前的列表(item),因为 concat 不会修改原数组,重新赋值给 result 数组
            result = result.concat(myFlat(item));
        } else {
            // 不是数组,则添加到 result 数组中
            result.push(item);
        }
    }
    // 返回结果
    return result;
}
// 方法二:
// some + 扩展运算符:通过 while 循环来持续判断当前项是否为数组,如果为数组,直接修改原数组 arr 等于 空数组展开当前数组,按此逻辑继续执行。
// some:如果有一个满足条件,则返回 true, 后续将和 includes 和 indexof 方法一样,不会再进行后续检测,如果不满足则返回 false
// any: 数组中的所有元素都满足条件,返回 boolean 值。
const MyFlat = (arr) => {
    while (arr.some((item) => Array.isArray(item))) {
        console.log(arr);
        arr = [].concat(...arr);
    }
    return arr;
};
// 方法三:
// split + toString(): 此方法弊端,如果数组中的元素都是数字,那经过此方法会直接转为字符串。
const MyFlat = (arr) => {
    return arr.toString().split(",");
};
// 方法四:
// ES6 flat
const MyFlat = (arr) => {
    return arr.flat(Infinity);
};
// test:
let arr = [1, [2, [3, 4, 5]]];
console.log("myFlat(arr) after------>", myFlat(arr)); // myFlat(arr) after------> [ 1, 2, 3, 4, 5 ]

手写 myInstanceof

/**
 * instanceof
 * instanceof 运算符用户检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
 * 语法:object(实例对象) instanceof constructor(构造函数,与 prototype 是成对出现的,你指向我,我指向你)
 * @param {Object} object 某个实例对象
 * @param {Function} constructorFn 某个构造函数
 * @return {Boolean}
 */
const myInstanceof = (object, constructorFn) => {
    // Object.getPrototypeOf(object) === object.__proto__; 都是用来获取某个对象的隐式原型
    let objectRes = Object.getPrototypeOf(object);
    // prototype:显式原型
    const constructorRes = constructorFn.prototype;
    while (true) {
        if (!objectRes) return false;
        // 如果构造函数的 prototype 在对象的实例中,直接返回 true
        if (objectRes === constructorRes) return true;
        // 继续向下寻找
        objectRes = Object.getPrototypeOf(objectRes);
    }
};
// test:
function F() { };
function D() { };
let f = new F();
// 表示: 构造函数 F 是否出现在 f 对象实例上
console.log(myInstanceof(f, F)); // true
// 表示: 构造函数 D 是否出现在 f 对象实例上
console.log(myInstanceof(f, D)); // false

特殊字符描述

问题标注 Q:(question)答案标注 R:(result)注意事项标准:A:(attention matters)详情描述标注:D:(detail info)总结标注:S:(summary)分析标注:Ana:(analysis)提示标注:T:(tips)

相关文章
|
6月前
|
前端开发
【面试题】如何使用ES6 ... 让代码优雅一点?
【面试题】如何使用ES6 ... 让代码优雅一点?
|
6月前
|
存储 前端开发 JavaScript
【面试题】你是如何让js 代码变得简洁的?
【面试题】你是如何让js 代码变得简洁的?
|
3月前
|
Java 编译器 C++
【Java基础面试一】、为什么Java代码可以实现一次编写、到处运行?
这篇文章解释了Java能够实现“一次编写,到处运行”的原因,主要归功于Java虚拟机(JVM),它能够在不同平台上将Java源代码编译成的字节码转换成对应平台的机器码,实现跨平台运行。
【Java基础面试一】、为什么Java代码可以实现一次编写、到处运行?
|
3月前
|
存储 缓存 Java
面试问Spring循环依赖?今天通过代码调试让你记住
该文章讨论了Spring框架中循环依赖的概念,并通过代码示例帮助读者理解这一概念。
面试问Spring循环依赖?今天通过代码调试让你记住
|
3月前
|
JavaScript 前端开发 程序员
JS小白请看!一招让你的面试成功率大大提高——规范代码
JS小白请看!一招让你的面试成功率大大提高——规范代码
|
5月前
|
存储 算法 Java
面试高频算法题汇总「图文解析 + 教学视频 + 范例代码」之 二分 + 哈希表 + 堆 + 优先队列 合集
面试高频算法题汇总「图文解析 + 教学视频 + 范例代码」之 二分 + 哈希表 + 堆 + 优先队列 合集
|
6月前
|
缓存 监控 算法
Python性能优化面试:代码级、架构级与系统级优化
【4月更文挑战第19天】本文探讨了Python性能优化面试的重点,包括代码级、架构级和系统级优化。代码级优化涉及时间复杂度、空间复杂度分析,使用内置数据结构和性能分析工具。易错点包括过度优化和滥用全局变量。架构级优化关注异步编程、缓存策略和分布式系统,强调合理利用异步和缓存。系统级优化则涵盖操作系统原理、Python虚拟机优化和服务器调优,需注意监控系统资源和使用编译器加速。面试者应全面理解这些层面,以提高程序性能和面试竞争力。
81 1
Python性能优化面试:代码级、架构级与系统级优化
|
6月前
|
数据采集 数据挖掘 Python
最全妙不可言。写出优雅的 Python 代码的七条重要技巧,2024年最新被面试官怼了还有戏吗
最全妙不可言。写出优雅的 Python 代码的七条重要技巧,2024年最新被面试官怼了还有戏吗
|
6月前
|
数据采集 XML 程序员
最新用Python做垃圾分类_python垃圾分类代码用key和format,5年经验Python程序员面试27天
最新用Python做垃圾分类_python垃圾分类代码用key和format,5年经验Python程序员面试27天
最新用Python做垃圾分类_python垃圾分类代码用key和format,5年经验Python程序员面试27天
|
6月前
|
数据采集 机器学习/深度学习 人工智能
最新用python代码画爱心,来自程序猿的浪漫~_python画爱心代码(1),2024年最新面试简历模板免费
最新用python代码画爱心,来自程序猿的浪漫~_python画爱心代码(1),2024年最新面试简历模板免费
最新用python代码画爱心,来自程序猿的浪漫~_python画爱心代码(1),2024年最新面试简历模板免费