考前答案

85 阅读5分钟
// 1、选择排序
const arr = [3, 4, 2, 5, 1, 6, 8, 7, 9]

(function fn() {
    let temp
    for (let p = 0; p <= arr.length - 2; p++) {
        let smallest = arr[p]
        let smallestIndex = p
        for (let i = p; i <= arr.length; i++) {
            if (arr[i] < arr[p]) {
                smallest = arr[i]
                smallestIndex = i
            }
        }
        temp = arr[p]
        arr[p] = smallest
        arr[smallestIndex] = temp
    }
    console.log(arr);
})

//冒泡排序
(function fn() {
    let temp
    for (let j = arr.length - 2; j >= 0; j--) {
        for (let i = 0; i <= j; i++) {
            if (arr[i] > arr[i + 1]) {
                temp = arr[i]
                arr[i] = arr[i + 1]
                arr[i + 1] = temp
            }
        }
    }
    console.log(arr);
})

// 2、深拷贝
(function fn(data) {
    let copy
    if (typeof (data) === 'function' || typeof (data) === 'object') {
        return data
    } else if (Array.isArray(data)) {
        copy = []
        data.forEach(function (item, index) {
            copy[index] = fn(item)
        })
        return copy
    } else {
        copy = {}
        for (let key in data) {
            copy[key] = fn(data[key])
        }
        return copy
    }
})

//3、手撸函数防抖与节流

//防抖
const inputHandler = function (e) {
    console.log(e.target);
    console.log(e.target.value);
}
ip.addEventListener('input', mydebounce(inputHandler, 1000))

function mydebounce(fn, delay) {
    let timer = null
    return function (...args) {
        if (timer) {
            clearTimeout(timer)
        }
        timer = setTimeout(() => {
            fn.apply(null, args)
            timer = null
        }, delay)
    }
}

// 节流
const clickHandler = function (e) {
    console.log('hello');
}
btn.addEventListener('click', mythrottle(clickHandler, 1000))

function mythrottle(fn, delay) {
    let timer = null
    return function (...args) {
        if (!timer) {
            fn.apply(null, args)
            timer = setTimeout(() => {
                timer = null
            }, delay)
        }
    }
}

// 4、使用连环异步回调实现求5的阶乘:
(function fn() {
    const multiply = (a, b, callback) => {
        setTimeout(() => callback(a * b), 2000);
    };
    const mulPromise = (a, b) => {
        return new Promise(
            (resolve, reject) => {
                multiply(a, b, (ret) => resolve(ret));
            }
        );
    };
    mulPromise(2, 3)
        .then((ret) => mulPromise(ret, 4))
        .then((ret) => mulPromise(ret, 5))
        .then((ret) => console.log("ret=", ret));

    ~(async function awaitDemo() {
        try {
            let ret = await mulPromise(2, 3);
            ret = await mulPromise(ret, 4);
            ret = await mulPromise(ret, 5);
            console.log(ret);
        } catch (err) {
            console.log("err=", err);
        }
    })();
})

// 5、提取URL中的查询参数
function getSearchParams(url) {
    const obj = {};
    const reg = /\w+=\w+/g
    const arr = url.match(reg)[a = 2, b = 3]
    arr.forEach((item) => {
        let [key, value] = item.split("=");
        obj[key] = value
    });
    return obj;
}

// 6、封装ajax,实现POST一个表单
~ function () {
    function getSearchParams(url = '') {
        const obj = {}
        url.match(/\w+=\w+/g).forEach(str => {
            let [key, value] = str.split('=')
            obj[key] = value
        })
        return obj
    }

    // obj = {
    //     name: 'heige',
    //     age: 12
    // }

    function toGetParams(obj) {
        let str = ''
        for (let key in obj) {
            str += `&${key}=${obj[key]}`
        }
        return str.slice(1)
    }

    function ajax({
        url,
        method,
        data,
        dataType,
        onSuccess,
        onFail
    }) {
        const xhr = new XMLHttpRequest()
        if (!url) {
            throw new Error('没给url')
        }
        method = method || 'GET'
        onSuccess = onSuccess || (data => console.log('default onSuccess:', data))
        onFail = onFail || (err => console.log('default onFail:', err))
        xhr.open(method, url)
        let reqBody = null
        switch (true) {
            case dataType == 'form':
                xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
                reqBody = toGetParams(data)
                break
            case dataType == 'json':
                xhr.setRequestHeader('Content-Type', 'application/json')
                reqBody = JSON.stringify(data)
                break
            default:
                break
        }
        xhr.onload = () => onSuccess(xhr.responseText)
        xhr.onerror = err => onFail(err)
        xhr.send(reqBody)
    }
    // try {
    //   ajax({
    //     url: 'http://www.httpbin.org/post',
    //     method: 'POST',
    //     dataType: 'form',
    //     data: { name: 'admin', pwd: '123456' },
    //     onSuccess: data => console.log(data),
    //     onFail: err => console.log(err)
    //   })
    // } catch (err) {
    //   console.log('catch err:', err);
    // }
    function ajaxPromise(config) {
        return new Promise((resolve, reject) => {
            ajax({
                ...config,
                onSuccess: data => resolve(data),
                onFail: err => reject(err),
            })
        })
    }
    ajaxPromise({
            url: 'http://www.httpbin.org/post',
            method: 'POST',
            dataType: 'form',
            data: {
                name: 'admin',
                pwd: '123456'
            },
        })
        .then(data => console.log(data))
        .catch(err => console.log(err))
}

// 7、带有超时功能的Promise
function fn() {
    async function executeWithTimeout(fn, ms) {
        return new Promise(async (resolve, reject) => {
            let timer = setTimeout(() => {
                reject("timeout");
            }, ms);
            const data = await fn();
            clearTimeout(timer);
            resolve(data);
        });
    }
    const timeout = 5000;

    function rq(url) {
        return new Promise((resolve) => {
            setTimeout(() => {
                resolve(`来自${url}的数据`);
            }, timeout);
        });
    }
    async function fn1() {
        return rq("https://www.taobao.com");
    }
    executeWithTimeout(fn1, 3000)
        .then((value) => console.log("value=", value))
        .catch((err) => console.log("err=", err));
}


// 8、一次性获取多个指定页面
function fn3() {
    async function getContentByUrl(url) {
        return new Promise((resolve, reject) =>
            setTimeout(() => {
                Math.random() > 0.5 ? resolve(`${url}的页面内容`) : reject("timeout");
            }, 1000)
        );
    }
    const urls = [
        "https://www.taobao.com",
        "https://www.baidu.com",
        "https://web.taobao.com",
    ];

    async function fetchData(urls = []) {
        return Promise.allSettled(
            urls
            .filter((url) => url.endsWith("taobao.com"))
            .map((url) => getContentByUrl(url))
        );
    }

    fetchData(urls)
        .then((results) => console.log(results));
}


// 9、IP地址比大小
function fn1() {
    function compare(ip1 = "", ip2 = "") {
        const arr1 = ip1.split(".").map((item) => item * 1);
        const arr2 = ip2.split(".").map((item) => item * 1);
        for (let i = 0; i < arr1.length; i++) {
            if (arr1[i] > arr2[i]) {
                return 1;
            }
            if (arr1[i] < arr2[i]) {
                return -1;
            }
        }
        return 0;
    }
    console.log(compare("1.2.3.4", "1.1.3.4"));
    console.log(compare("1.11.3.4", "1.2.3.4"));
    console.log(compare("1.2.3.4", "1.11.3.4"));
    console.log(compare("1.2.3.4", "1.2.3.4"));
}

// 10、实现闭包管理全班学生成绩
function score(name) {
    const scores = {
        chinese: 0,
        math: 0,
        coding: 0,
    };

    return {
        set(key, value) {
            scores[key] = value;
        },

        getAll() {
            return `${name}:${JSON.stringify(scores)}`;
        },
    };
}
const arr1 = ["张三疯", "尼古拉斯赵四", "隔壁老王"]
const obj = {}
arr1.forEach(
    name => obj[name] = scrore(name)
)

// 11、手封MyMap实现一下效果
class MyMap {
    constructor() {
        this.obj = {};
        this.size = 0;
    }

    set(key, value) {
        this.obj[key] = value;
        this.updateSize();
    }

    get(key) {
        return this.obj[key];
    }

    updateSize() {
        this.size = Object.keys(this.obj).length;
    }

    delete(key) {
        delete this.obj[key];
        this.updateSize();
    }

    clear() {
        this.obj = {};
        this.size = 0;
    }

    has(key) {
        return this.obj.hasOwnProperty(key);
    }

    forEach(handler) {
        for (let key in this.obj) {
            handler.apply(this, [this.obj[key], key, this]);
        }
    }

    keys() {
        return Object.keys(this.obj);
    }

    values() {
        return Object.keys(this.obj).map((key) => this.obj[key]);
    }

    entries() {
        return Object.keys(this.obj).map(
            (key) => ({
                key,
                value: this.obj[key]
            })
        );
    }
}

~(function () {
    const map = new MyMap()
    map.set("name", "张三")
    map.set("age", 20)
    map.set("gender", "男")

    map.forEach(
        (value, key) => console.log(key, value)
    )

    for (let entry of map.entries()) {
        console.log(entry)
    }

    console.log(map.size)
    console.log(map.get("name"))
    console.log(map.get("age"))

    console.log(map.has("name"))
    console.log(map.has("myname"))

    map.delete("age")
    map.clear()
    console.log(map.size)
})


// 12、全班人马排除空座位后抽取N名幸运观众
function fn3() {
    let stus = [];
    for (let i = 1; i < 100; i++) {
        stus.push(i);
    }
    const empties = [12, 34, 56, 78];
    stus = stus.filter((s) => empties.indexOf(s) === -1);
    const pick = (arr, n) => {
        let luckies = [];
        for (let i = 0; i < n; i++) {
            let randomIndex = parseInt(Math.random() * arr.length);
            luckies = arr.splice(randomIndex, 1).concat(luckies)
        }

        return luckies;
    };
    console.log(pick(stus, 5));
}
// fn3();


// 13、手撸观察者模式:实现彩票机周期性地发布【开售】【开奖】事件,玩家开售时下注,开奖时购买,一旦中奖则彩票机停止工作;
function observerDemo() {
    class Observable {
        constructor(name) {
            this.name = name;
            this.observers = [];
        }
        register(ob) {
            this.observers.push(ob);
            ob.observable = this;
        }
        unregister(ob) {
            this.observers = this.observers.filter((o) => o !== ob);
        }
        emit(event) {
            this.observers.forEach((ob) => ob.onEvent(event));
        }
    }
    class Observer {
        constructor(name) {
            this.name = name;
        }
        onEvent(event) {
            console.log(this.name, "响应事件", event);
        }
    }
    class Lottery extends Observable {
        constructor(name) {
            super(name);
            this.timer = null;
        }
        start() {
            if (!this.timer) {
                this.timer = setInterval(() => {
                    const code = parseInt(Math.random() * 3);
                    console.log(this.name, "发布开奖事件", code);
                    this.emit({
                        type: "开奖",
                        code
                    });
                    this.emit({
                        type: "开售"
                    });
                }, 2000);
            }
        }
        stop() {
            if (this.timer) {
                clearInterval(this.timer);
                console.log(this.name, "已停止");
                this.timer = null;
            }
        }
    }
    class Player extends Observer {
        constructor(name) {
            super(name);
            this.code = null;
        }
        buy() {
            this.code = parseInt(Math.random() * 3);
            console.log(this.name, "下注", this.code);
        }
        check(event) {
            const isLucky = this.code === event.code;
            console.log(this.name, isLucky ? "中奖了" : "未中奖");
            isLucky && this.observable.stop();
        }
        onEvent(event) {
            super.onEvent(event);
            switch (event.type) {
                case "开售":
                    this.buy();
                    break;
                case "开奖":
                    this.check(event);
                    break;

                default:
                    break;
            }
            console.log("");
        }
    }

    ~(function main() {
        const lot = new Lottery("六合彩");
        const tiger = new Player("打老虎");
        const gaojin = new Player("高进");

        lot.register(tiger);
        lot.register(gaojin);
        lot.unregister(gaojin);

        lot.start();
    })();
}
// observerDemo();


// 14、实现任意多个入参的函数fn的柯里化
function curryDemo() {
    const curry = (fn) => {
        return function cfn(...args) {
            if (args.length === fn.length) {
                return fn.apply(null, args);
            }

            return function (...b) {
                args = args.concat(b);
                return cfn(...args);
            };
        };
    };

    const cadd = curry(add);
    console.log(cadd(1, 2, 3, 4));
    console.log(cadd(1, 2)(3)(4));
}
// curryDemo();

// 15、实现任意多个函数的管道与组合
function pipeDemo() {
    const pipe = (...fns) => (v => fns.reduce(
        (pv, fn, index) => fn(pv),
        v
    ))
    const compose = (...fns) => (v => fns.reverse().reduce(
        (pv, fn, index) => fn(pv),
        v
    ))

    const len = (n) => (n + "").length;
    const pow = (n) => n * n;
    const cubicRoot = (n) => Math.cbrt(n);
    console.log(compose(len, pow, cubicRoot)(1000));
}
// pipeDemo();

// 16、函数的Promise化
async function promDemo() {
    function promisify(fn) {
        return function (...args) {
            return new Promise(
                (resolve, reject) => {
                    try {
                        resolve(fn.apply(null, args))
                    } catch (err) {
                        reject(err)
                    }
                }
            )
        }
    }

    const add = (a, b, c, d) => {
        if (Math.random() > 0.7) {
            throw new Error("人品槽已空,请尽快充100块钱的人品")
        }
        return a + b + c + d
    }
    const pow = (a, b) => {
        if (Math.random() > 0.7) {
            throw new Error("人品槽已空,请尽快充100块钱的人品")
        }
        return Math.pow(a, b)
    }

    const padd = promisify(add)
    const ppow = promisify(pow)

    // padd(1,2,3,4).then(
    //     data => {
    //         console.log("data=",data)
    //         return ppow(data,2)
    //     }
    // )
    // .then(
    //     data => console.log("data=",data)
    // )
    // .catch(
    //     err => console.error("err=",err)
    // )

    try {
        let data = await padd(1, 2, 3, 4)
        console.log("data=", data)

        data = await ppow(data, 2)
        console.log("data=", data)
    } catch (err) {
        console.error("err=", err)
    }

}
// promDemo()

// 17、封装MongoDB数据引擎层 
async function fn3() {
    function getCollection(dbName, collectionName) {
        return new Promise(
            (resolve, reject) => {
                var MongoClient = require("mongodb").MongoClient;
                var url = "mongodb://localhost:27017/";

                MongoClient.connect(url, function (err, conn) {
                    if (err) {
                        resolve({
                            err,
                            collection: undefined,
                            conn: undefined,
                        });
                        return;
                    }

                    var dbo = conn.db(dbName);
                    const collection = dbo.collection(collectionName);
                    resolve({
                        err: undefined,
                        collection,
                        conn,
                    });
                });
            }
        );
    }

    async function doCreate(dbName, collectionName, dataObj) {
        const {
            err,
            collection,
            conn
        } = await getCollection(
            dbName,
            collectionName
        );
        if (err) {
            return {
                err,
                res: undefined,
            };
        }

        collection.insertOne(dataObj, function (err, res) {
            conn.close();
            return {
                err,
                res,
            };
        });
    }
    async function addUser(user) {
        const ret = await doCreate(dbName, collectionName, user);
        return ret;
    }
}
// fn3();

//18、异步函数的Promise化 
function fn2() {
    function add(a, b) {
        return a + b;
    }

    function multiply(a, b, callback) {
        setTimeout(() => callback(a * b), 1000);
    }

    function promisify(fn) {
        return function pfn(...args) {
            return new Promise(
                (resolve, reject) => {
                    const ret = fn.apply(null, [...args, (...a) => resolve(a)]);
                    ret && resolve(ret);
                }
            );
        };
    }

    /* 同步返回函数的Promise化 */
    //   const padd = promisify(add);
    //   padd(2, 3).then(
    //     (value) => console.log("value=", value) //5
    //   );

    const pmul = promisify(multiply);
    pmul(2, 3)
        .then((values) => {
            console.log("value=", values);
            return pmul(values[0], 4);
        })
        .then((values) => {
            console.log("value=", values);
            return pmul(values[0], 5);
        })
        .then((values) => console.log(values[0]));
}
// fn2();


//19、 手撸数据驱动视图微框架
function defineReactive(data, keys = []) {
    keys.forEach(
        ({
            name,
            listeners
        }) => {
            Object.defineProperty(data, name, {
                get() {
                    console.log("get", name);
                    return data[`x_${name}`];
                },
                set(newValue) {
                    console.log("set", name, newValue);
                    data[`x_${name}`] = newValue;
                    listeners.forEach((dom) => (dom.innerText = newValue));
                },
            });
        }
    );
}

const data = {};
defineReactive(data, [{
        name: "age",
        listeners: [hMyage, pMyage]
    },
    {
        name: "name",
        listeners: [hMyname, pMyname]
    },
    {
        name: "gender",
        listeners: [pGender]
    },
]);
data.name = "黑哥";
data.age = 18;
data.gender = "男";
setInterval(() => {
    data.name = Date.now();
    data.age = data.age + 1;
    data.gender = data.gender === "男" ? "女" : "男";
}, 1000);

//20、数组APIreduce

const arr12=[1,2,3,4]
const initialValue=0
const sunWithInitial=arr12.reduce((previousValue,currentValue)=>previousValue+currentValue,initialValue)
console.log(sunWithInitial);