自己的一些手写备忘录

161 阅读3分钟

1、数组相关

// es5实现数组去重
function unique(arr) {
    var res = arr.filter((item, index, array) => { return array.indexOf(item) === index })
    return res
}
// es6实现数组去重
var unique2 = (arr) => [...new Set(arr)]
console.log(unique2([1, 2, 2, 4, 5, 6, 6, 7]));

// 数组打平
console.log([1, [2, 5]].flat()); // 使用了打平的API
// 自己手写,不使用API
function flatten(arr) {
    let result = [];
    const len = arr.length;
    for (let i = 0; i < len; i++) {
        if (Array.isArray(arr[i])) {
            result = result.concat(flatten(arr[i]));
        } else {
            result = result.concat(arr[i]);
        }
    }

    return result;
}

// 洗牌算法乱序一个数组
function shuttle(arr) {
    const len = arr.length;
    for(let i = len - 1; i > -1; i--) {
        let indexRandom = Math.floor(i * Math.random());
        [arr[i], arr[indexRandom]] = [arr[indexRandom], arr[i]]
    }
    return arr
}

2、防抖节流

// 防抖
function myDebounce(fn, delay) {
    var timeout;
    return function () {
        clearTimeout(timeout)
        timeout = setTimeout(() => {
            fn.apply(this, arguments);
        }, delay);
    }
}

// 节流
function myThrottle(fn, delay){
    var lastTime = 0;
    return function () {
        var curTime = +Date.now();
        if(curTime - lastTime > delay) {
            fn.apply(this, arguments);
            lastTime = curTime;
        }
    }
}

3、事件总线

// 实现事件总线
class myEvent {
    constructor() {
        this.events = {};
    }
    on(name, fn) {
        if(this.events[name]) {
            this.events[name].push(fn)
        } else {
            this.events[name] = [fn];
        }
    }
    off(name, fn) {
        if(!this.events[name]) {
            return
        } else {
            for(let i = 0; i < this.events[name].length; i++) {
                if(this.events[name][i] == fn) {
                    this.events[name].splice(i, 1)
                }
            }
        }
    }
    fire(name, ...args) {
        let task = this.events[name]
        for(let item of task) {
            item(...args);
        }
    }
}

4、实现ajax

// 基础实现ajax
function myAjax(url, method, data) {
    return new Promise((resolve, reject) => {
        var xhr = new XMLHttpRequest;
        xhr.open(url, method);
        xhr.send(data || null);
        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    resolve(JSON.parse(xhr.responseText))
                } else if (xhr.status > 400) {
                    reject('发生错误')
                }
            }
        }
    })
}

5、实现js继承

// ES6实现继承,使用class
class Parent {
    constructor(name) {
        this.name = name;
    }
    print() {
        console.log('name is ' + this.name + this.id);
    }
}

class Child extends Parent {
    constructor(name, id) {
        super(name);
        this.id = id;
    }
}

let child = new Child('test', 19);
child.print();

// ES5实现继承,寄生式组合继承
function parent2(name) {
    this.name = name;
}

parent2.prototype.print2 = function () { console.log('name is ' + this.name); }

function child2(name, id) {
    parent2.call(this, name);
    this.id = id;
}
child2.prototype = Object.create(parent2.prototype);
child2.prototype.constructor = child2;

// 一些测试
let o1 = new child2('test2', 2);
let o2 = new child2('test3', 8);
o1.print2();
console.log(o1.sex);
o2.print2();
console.log(o2.sex);

6、实现函数原型方法

// 实现函数原型方法,apply
Function.prototype.myapply = function (conText, args) {
    // 默认指向window
    conText = conText || window;
    args = args || [];
    // 新增一个独一无二的属性,隐式绑定
    let key = Symbol();
    conText[key] = this;
    // 调用函数
    let result = conText[key](...args);
    // 删除新增的辅助属性
    delete conText[key];
    return result
}

// 实现函数原型方法,apply
Function.prototype.mycall = function (conText, ...args) {
    // 默认指向window
    conText = conText || window;
    args = args || [];
    // 新增一个独一无二的属性,隐式绑定
    let key = Symbol();
    conText[key] = this;
    // 调用函数
    let result = conText[key](...args);
    // 删除新增的辅助属性
    delete conText[key];
    return result
}

// 实现函数原型方法,bind 
Function.prototype.myBind = function (context, ...args) {
    const fn = this
    args = args ? args : []
    return function newFn(...newFnArgs) {
        if (this instanceof newFn) {
            return new fn(...args, ...newFnArgs)
        }
        return fn.apply(context, [...args,...newFnArgs])
    }
}


var arr1 = [1, 2];
var arr2 = [3, 4, 5];
arr1.push.mycall(arr1, 3, 4, 5);
console.log(arr1);

7、实现深浅拷贝

let obj1 = {id: 2, name: 'eee', demo:{id: 2}};
// 简单浅拷贝
let obj2 = {...obj1};
// 实现深拷贝,解决循环引用问题
function mydeepClone(obj, cache = new WeakMap) {
    if(typeof obj !== 'object') return obj;
    if(obj instanceof Date) return new Date(obj);
    if(obj instanceof RegExp) return new RegExp(obj);
    if(cache.get(obj)) return cache.get(obj);
    cache.set(obj, true);
    let cloneobj = new obj.constructor();
    for(let key in obj){
        if(obj.hasOwnProperty(key)){
            cloneobj[key] = mydeepClone(obj[key], cache)
        }
    }
    return cloneobj
}

8、解析URL参数

// 使用API
const urlSearchParams = new URLSearchParams('?sku=17240758191&ptag=1');
console.dir(Object.fromEntries(urlSearchParams.entries()));

// 不使用API
function getParams(url) {
    var res = {};
    if (url.indexOf('?')) {
        let urlParamsArr = url.split('?')[1].split('&');
        urlParamsArr.map((item) => {
            let key = item.split('=')[0];
            let value = item.split('=')[1];
            res[key] = decodeURIComponent(value);
        })
    }
    return res
}

9、排序算法

// 冒泡排序
function sortBuddle(arr) {
    const len = arr.length;
    for (let i = 0; i < len; i++) {
        for (let j = 1; j < len - i; j++) {
            if (arr[j] < arr[j - 1]) {
                [arr[j], arr[j - 1]] = [arr[j - 1], arr[j]]
            }
        }
    }
    return arr
}
// 快速排序
function QuickSort(arr, low, high) {
    let left = low;
    let right = high;
    let basic = arr[low];
    while (left < right) {
        while (left < right && arr[right] > basic) {
            right--;
        }
        while (left < right && arr[left] <= basic) {
            left++;
        }
        if (left < right) {
            [arr[left], arr[right]] = [arr[right], arr[left]];
        } else {
            [arr[low], arr[left]] = [arr[left], arr[low]];
            QuickSort(arr, low, left - 1);
            QuickSort(arr, right + 1, high);
        }
    }
    return arr
}
// 选择排序
function SelectionSort (arr) {
    const len = arr.length
    for (let i = 0; i < len; i++ ) {
        let minIndex= i
        for (let j = i + 1; j < len; j++) {
            minIndex = arr[minIndex] <= arr[j] ? minIndex : j
        }
        if (minIndex !== i) {
            [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
        }
    }
    return arr
}

10、实现Promise

// 了解Promise是如何实现异步的,以及then方法如何实现链式调用
class MyPromise {
    constructor(executor) {
        this.status = 'pending'; 
        this.value = null; 
        this.reason = null; 
        this.onFulfilledCallbacks = []; 
        this.onRejectedCallbacks = [];
        let resolve = (value) => {
            if(this.status === 'pengding') {
                this.status = 'fulfilled';
                this.value = value;
                this.onFulfilledCallbacks.forEach(fn => fn());
            }
        }
        let reject = (reason) => {
            if(this.status === 'pending') {
                this.status = 'rejected';
                this.reason = reason;
                this.onRejectedCallbacks.forEach(fn => fn());
            }
        }
        try {
            executor(resolve, reject);
        } catch (error) {
            reject(error)
        }
    }
    then(onFulfilled, onRejected) {
        return new MyPromise((resolve, reject) => {
            if(this.status === 'fulfilled') {
                try {
                    setTimeout(() => {
                        let x = onFulfilled(this.value);
                        x instanceof MyPromise ? x.then(resolve, reject) : resolve(x);
                    });
                } catch (err) {
                    reject(e);
                }
            }
            if(this.status === 'rejected') {
                try {
                    setTimeout(() => {
                        let x = onRejected(this.reason);
                        x instanceof MyPromise ? x.then(resolve, reject) : resolve(x);
                    });
                } catch (err) {
                    reject(err)
                }
            }
            if(this.status === 'pending') {
                this.onFulfilledCallbacks.push(
                    () => {
                        try {
                            setTimeout(() => {
                                let x = onFulfilled(this.value);
                                x instanceof MyPromise ? x.then(resolve, reject) : resolve(x);
                            });
                        } catch (err) {
                            reject(e);
                        }
                    }
                );
                this.onRejectedCallbacks.push(
                    () => {
                        try {
                            setTimeout(() => {
                                let x = onRejected(this.reason);
                                x instanceof MyPromise ? x.then(resolve, reject) : resolve(x);
                            });
                        } catch (err) {
                            reject(err)
                        }
                    }
                )
            }
        });
    }
}

11、实现Promise.all

Promise.myAll = function(promisearr) {
    let count = 0, res = [];
    return new Promise((resolve, reject) => {
        promisearr.forEach((item, index) => {
            Promise.resolve(item).then(value => {
                res[index] = value;
                count++;
                if(count == promisearr.length) {
                    resolve(res)
                }
            }).catch((err) => reject(err))
        });
    })
}

12、实现Promise.race

Promise.myRace = function(promisearr) {
    return new Promise((resolve, reject) => {
        promisearr.forEach((item) => {
            Promise.resolve(item).then(resolve, reject);
        })
    })
}

13、二分查找

function BinarySearch(arr, target) {
    if (arr.length <= 1) return -1
    // 低位下标
    let lowIndex = 0
    // 高位下标
    let highIndex = arr.length - 1
    while (lowIndex <= highIndex) {
        // 中间下标。
        const midIndex = Math.floor((lowIndex + highIndex) / 2)
        if (target < arr[midIndex]) {
            highIndex = midIndex - 1
        } else if (target > arr[midIndex]) {
            lowIndex = midIndex + 1
        } else {
            return midIndex
        }
    }
    return -1
}