опрос! Вы действительно готовы? |Прочесывание серии API рукописного ввода

JavaScript
опрос! Вы действительно готовы? |Прочесывание серии API рукописного ввода

"Не бойся, не обращай внимания, работай впредь" - Всем привет! Я Маленький Сезам 😄

Титульная вечеринка, она снова, снова, снова...

Эта статья представляет собой сводку всех API-интерфейсов, которые Xiaosesame написала и не написала ранее, в рамках подготовки к общему обзору позже.Если вам это просто нужно, просмотрите его с Xiaosesame😄 ;

1. Имитация серии

1. Переписать вызов

(proto => {
    function myCall(thisArg, ...args) {
        thisArg = thisArg == undefined ? window : thisArg;
        let type = typeof thisArg;
        if (!/^(object|function)$/.test(type)) {
            if (/^(symbol|bigint)$/.test(type)) {
                thisArg = Object(thisArg);
            } else {
                thisArg = new thisArg.constructor(thisArg);
            }
        }
        let key = Symbol('key');
        thisArg[key] = this;
        let result = thisArg[key](...args);
        delete thisArg[key];
        return result;
    }
    proto.myCall = myCall;
})(Function.prototype)

2, переписать применять

(proto => {
    function myApply(thisArg, args) {
        thisArg = thisArg == undefined ? window : thisArg;
        let type = typeof thisArg;
        if (!/^(object|function)$/.test(type)) {
            if (/^(symbol|bigint)$/.test(type)) {
                thisArg = Object(thisArg);
            } else {
                thisArg = new thisArg.constructor(thisArg);
            }
        }
        let key = Symbol('key');
        thisArg[key] = this;
        let result = thisArg[key](args);
        delete thisArg[key];
        return result;
    }
    proto.myApply = myApply;
})(Function.prototype)

3. Переписать привязку

(proto => {
    function myBind(thisArg, ...args) {
        let _this = this;
        thisArg = thisArg == undefined ? window : thisArg;
        let type = typeof thisArg;
        if (!/^(object|function)$/.test(type)) {
            if (/^(symbol|bigint)$/.test(type)) {
                thisArg = Object(thisArg);
            } else {
                thisArg = new thisArg.constructor(thisArg);
            }
        }
        return function an(...innerArgs) {
            _this.call(thisArg, ...args.concat(innerArgs));
        }
    }
    proto.myBind = myBind;
})(Function.prototype)

4. Переписать новый

function Dog(name) {
    this.name = name;
}
Dog.prototype.bark = function () {
    console.log('wangwang');
}
Dog.prototype.sayName = function () {
    console.log('my name is ' + this.name);
}
//==========重写开始
function _new(Func, ...args) {
    let obj = Object.create(Func.prototype);
    let result = Func.call(obj, ...args);
    if (result !== null && /^(object|function)$/.test(typeof result)) return result;
    return obj;
}
//==========重写结束
let sanmao = _new(Dog, '三毛');
sanmao.bark(); //=>"wangwang"
sanmao.sayName(); //=>"my name is 三毛"
console.log(sanmao instanceof Dog); //=>true 

Во-вторых, серия инструментов

1. Защита от сотрясения

debounce: Функция anti-shake заключается не в выполнении функции при завершении события, а в выполнении ее только один раз через определенный интервал, чтобы избежать чрезмерного выполнения функций

  • @параметры:
    • func: функция, которую необходимо выполнить
    • ждать: установить интервал времени
    • немедленно: если установлено значение true, вызов срабатывает на начальной границе, а не на конечной.
  • @return: возвращает вызываемую функцию
let debounce = function (func, wait, immediate) {
    //=>result用来存储函数执行返回的结果
    //=>timeout记录定时器
    let result,
        timeout = null;
    //=>返回可被执行的函数
    return function (...args) {
        //=>now记录的是事件触发的时候立即执行,还是需要等待间隔事件后执行
        let context = this,
            now = immediate && !timeout;
        //=>每一次设置新的定时器等待之前,都要先清空上一次设置的,确保间隔时间内只执行一次
        clearTimeout(timeout);
        //=>设置定时器:到达时间间隔后执行函数
        timeout = setTimeout(() => {
            timeout = null;
            if (!immediate) result = func.apply(context, args);
        }, wait);
        //=>如果是事件触发就执行,把函数执行即可
        if (now) result = func.apply(context, args);
        return result;
    };
};

2. Дросселирование

дроссель: функция дросселирования заключается в снижении частоты выполнения, при достижении определенного временного интервала она будет выполняться один раз

  • @параметры:
    • func: функция, которую необходимо выполнить
    • ждать: установить интервал времени
  • @return: возвращает вызываемую функцию
let throttle = function (func, wait) {
    let timeout = null,
        result = null,
        previous = 0; //=>上次执行时间点
    return function (...args) {
        let now = new Date,
            context = this;
        //=>remaining小于等于0,表示上次执行至此所间隔时间已经超过一个时间间隔
        let remaining = wait - (now - previous);
        if (remaining <= 0) {
            clearTimeout(timeout);
            previous = now;
            timeout = null;
            result = func.apply(context, args);
        } else if (!timeout) {
            timeout = setTimeout(() => {
                previous = new Date;
                timeout = null;
                result = func.apply(context, args);
            }, remaining);
        }
        return result;
    };
};

3. Глубокий клон

Глубокое клонирование VS поверхностное клонирование | Глубокое сравнение VS поверхностное сравнение | Функции обратного вызова

метод первый:

let clone = JSON.parse(JSON.stringify(obj));

Способ второй:

function _cloneDeep(obj) {
    if (obj === null) return null;
    if (typeof obj !== "object") return obj;
    if (obj instanceof RegExp) return new RegExp(obj);
    if (obj instanceof Date) return new Date(obj);
    let cloneObj = new obj.constructor;
    for (let key in obj) {
        if (!obj.hasOwnProperty(key)) continue;
        cloneObj[key] = _cloneDeep(obj[key]);
    }
    return cloneObj;
}

По инструкции мастеров, здесьbreakпревратиться вcontinue, обязательно опустите любую частную собственность, это более уместно 😄

4. Глубокое слияние

function _assignDeep(obj1, obj2) {
    let obj = _cloneDeep(obj1);
    for (let key in obj2) {
        if (!obj2.hasOwnProperty(key)) continue;
        let v2 = obj2[key],
            v1 = obj[key];
        if ((v1 !== null && typeof v1 === "object") && (v2 !== null && typeof v2 === "object")) {
            obj[key] = _assignDeep(v1, v2);
            continue;
        }
        obj[key] = v2;
    }
    return obj;
}

5. Подробное сравнение

  • Значение базового типа данных можно сравнить на основе ===
  • Функция: преобразовать оба в строки, а затем сравнить
  • Объект:
    • => регулярное выражение/дата: оба преобразуются в строки, а затем сравниваются
    • => обычный объект/объект массива и т. д.:
      • 1) Количество частных владений
      • 2) Пройдите каждый атрибут отдельно, чтобы увидеть, согласованы ли значения атрибута.
function _is(val1, val2) {
    const type1 = val1 === null ? 'null' : typeof val1,
        type2 = val2 === null ? 'null' : typeof val2;
    // 函数
    if (type1 === "function" && type2 === "function") {
        return val1.toString() === val2.toString();
    }
    // 对象
    if (type1 === "object" && type2 === "object") {
        // 正则和日期
        const ct1 = val1.constructor,
            ct2 = val2.constructor;
        if ((ct1 === RegExp && ct2 === RegExp) || (ct1 === Date && ct2 === Date)) {
            return val1.toString() === val2.toString();
        }
        // 其它对象
        const keys1 = Object.keys(val1),
            keys2 = Object.keys(val2);
        if (keys1.length !== keys2.length) return false;
        for (let i = 0; i < keys1.length; i++) {
            let key1 = keys1[i],
                key2 = keys2[i];
            if (key1 !== key2) return false;
            let item1 = val1[key1],
                item2 = val2[key2];
            let flag = _is(item1, item2);
            if (!flag) return false;
        }
        return true;
    }
    // 其它
    return val1 === val2;
}

6. Определение типа данных

function toType(obj) {
    let class2type = {};
    ["Boolean", "Number", "String", "Function", "Array", "Date", "RegExp", "Object", "Error", "Symbol"].forEach(
        item => {
            class2type["[object " + item + "]"] = item.toLowerCase();
        });
    if (obj == null) return obj + "";
    return typeof obj === "object" || typeof obj === "function" ?
        class2type[class2type.toString.call(obj)] || "object" :
        typeof obj;
}

let obj = function () {};
console.log(toType(obj))

7. Прототипное наследование

Подробнее о наследовании можно посмотреть здесь:Различные методы наследования в JS

function Parent() {
    this.x = 100;
}

function Child() {
    this.y = 200;
}
//=> 让子类的原型等于父类的实例
Child.prototype = new Parent; //=>原型继承

Child.prototype.getY = function getY() {
    return this.y;
};

let c1 = new Child;
console.log(c1);

8. НАСЛЕДОВАНИЕ ВЫЗОВА

function Parent() {
    this.x = 100;
}
Parent.prototype.getX = function getX() {
    return this.x;
};

function Child() {
    // 在子类构造函数中,把父类当做普通方法执行(没有父类实例,父类原型上的那些东西也就和它没关系了)
    // this -> Child的实例c1
    Parent.call(this); // this.x=100 相当于强制给c1这个实例设置一个私有的属性x,属性值100,相当于让子类的实例继承了父类的私有的属性,并且也变为了子类私有的属性 “拷贝式”
    this.y = 200;
}
Child.prototype.getY = function getY() {
    return this.y;
};

let c1 = new Child;
console.log(c1);

9. Наследование паразитарного состава

function Parent() {
    this.x = 100;
}
Parent.prototype.getX = function getX() {
    return this.x;
};
function Child() {
    Parent.call(this);
    this.y = 200;
}

Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

Child.prototype.getY = function getY() {
    return this.y;
};

let c1 = new Child;
console.log(c1);

10. Отформатируйте строку времени

String.prototype.formatTime = function formatTime(template) {
    // 1.根据操作的时间字符串获取年月日小时分钟秒等信息
    let arr = this.match(/\d+/g).map(item => {
        return item.length < 2 ? '0' + item : item;
    });

    // 2.解析格式化的模板,找到对应的时间,替换模板中的内容
    template = template || '{0}年{1}月{2}日 {3}时{4}分{5}秒';
    return template.replace(/\{(\d+)\}/g, (_, group) => {
        return arr[group] || "00";
    });
};

11. Обработка параметров URL

Три метода обработки параметров URL в JS

Способ 1: замена обработки

(proto => {
    function queryURLParams() {
        let obj = {};
        this.replace(/([^?=&#]+)=([^?=&#]+)/g, (_, key, value) => obj[key] = value);
        this.replace(/#([^?=&#]+)/g, (_, hash) => obj['HASH'] = hash);
        return obj;
    }
    proto.queryURLParams = queryURLParams;
})(String.prototype);

console.log('http://www.xxxxxxx.cn/?lx=1&name=JS&from=baidu#video'.queryURLParams());

Способ 2. Используйте встроенный метод тега A.

function queryURLParams(url) {
    // 1.创建A标签(A元素对象)来获取到问号参数和哈希值
    let link = document.createElement('a');
    link.href = url;
    let askText = link.search.substr(1),
        polText = link.hash.substr(1),
        obj = {};
    // 2.向对象中进行存储
    polText ? obj['HASH'] = polText : null;
    if (askText) {
        let arr = askText.split(/(?:&|=)/g); //=>同时按照两个字符来拆分:["lx", "1", "name", "JS", "from", "baidu"]
        for (let i = 0; i < arr.length; i += 2) {
            // console.log(arr[i], arr[i + 1]); 属性名和属性值
            obj[arr[i]] = arr[i + 1];
        }
    }
    return obj;
}
let result = queryURLParams('http://www.xxxxxxx.cn/?lx=1&name=JS&from=baidu#video');
console.log(result);

/* <a href="http://www.xxxxxxx.cn/?lx=1&name=JS&from=baidu#video" id="link">*/

12. Внедрить разделители тысяч

String.prototype.millimeter = function millimeter() {
    return this.replace(/\d{1,3}(?=(\d{3})+$)/g, value => {
        return value + ',';
    });
};

13. Символ с наибольшим количеством вхождений в строку

let str = "hello";
let ary = [...new Set(str.split(''))];
let max = 0;
let code = '';
for (let i = 0; i < ary.length; i++) {
    let reg = new RegExp(ary[i], 'g');
    let val = str.match(reg).length;  
    if (val > max) {
        max = val;
        code = ary[i];
    } else if (val === max) {
        code = `${code}、${ary[i]}`;
    }
}
console.log(`出现次数最多的字符是:${code},次数为:${max}`); 

Этот метод цитируется: Nuggets Автор:Хэппи Лииз[Рекомендуемая коллекция] Краткие сведения о внешнем интерфейсе; (PS: Говорят, что это очень красивая барышня 🌹 )

14. Дедупликация массива

Три способа дедупликации массивов в JS

Способ 1: Двойной цикл for

for (let i = 0; i < arr.length - 1; i++) {
    let item = arr[i];
    for (let j = i + 1; j < arr.length; j++) {
        if (item === arr[j]) {
            arr[j] = arr[arr.length - 1];
            arr.length--;
            j--;
        }
    }
}
console.log(arr);

Способ 2: Путь пары ключ-значение объекта

let arr = [1, 2, 3, 1, 1, 4, 2, 3];
let obj = {};
for (let i = 0; i < arr.length; i++) {
    let item = arr[i];
    if (obj[item] !== undefined) {
        arr[i] = arr[arr.length - 1];
        arr.length--;
        i--;
        continue;
    }
    obj[item] = item;
}
console.log(arr);

Способ 3: ES6 использует метод Set

/* ES6中没有提供现成的去重办法,但是提供了一些去重的方式 :Set数据结构*/
let obj = { y: 200 };
let arr = [obj, 1, 2, 3, 1, obj, 1, 4, 2, 3, '3', { x: 100 }, { x: 100 }];
arr = Array.from(new Set(arr));
console.log(arr);

15. Сортировка массива

Способ 1: пузырьковая сортировка

// 交换位置函数
function swap(arr, i, j) {
    let temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
    return arr;
}
Array.prototype.bubble = function bubble() {
    // 外层循环I控制比较的轮数
    for (let i = 0; i < this.length - 1; i++) {
        // 里层循环控制每一轮比较的次数J
        for (let j = 0; j < this.length - 1 - i; j++) {
            if (this[j] > this[j + 1]) {
                // 当前项大于后一项,交换位置
                swap(this,j,j+1);
            }
        }
    }
    return this;
}
let ary = [12, 8, 24, 16, 1];
ary.bubble();
console.log(ary);

Метод 2: Сортировка отбора

Array.prototype.select = function select() {
    for (let j = 0; j < this.length - 1; j++) {
        let min = j,
            temp = null;
        // 找到比当前项还小的这一项索引
        for (let i = min + 1; i < this.length; i++) {
            if (this[i] < this[min]) {
                min = i;
            }
        }
        // 让最小的项和当前首位交换位置
        swap(this,min,j);
    }
    return this;
};
let ary = [12, 8, 24, 16, 1];
ary.select();
console.log(ary);

Способ 3: сортировка вставками

Array.prototype.insert = function insert() {
    // 1.准备一个新数组,用来存储抓到手里的牌,开始先抓一张牌进来
    let handle = [];
    handle.push(this[0]);

    // 2.从第二项开始依次抓牌,一直到把台面上的牌抓光
    for (let i = 1; i < this.length; i++) {
        // A是新抓的牌
        let A = this[i];
        // 和HANDDLE手里的牌依次比较(从后向前比)
        for (let j = handle.length - 1; j >= 0; j--) {
            // 每一次要比较的手里的牌
            let B = handle[j];
            // 如果当前新牌A比要比较的牌B大了,把A放到B的后面
            if (A > B) {
                handle.splice(j + 1, 0, A);
                break;
            }
            // 已经比到第一项,我们把新牌放到手中最前面即可
            if (j === 0) {
                handle.unshift(A);
            }
        }
    }
    return handle;
}
let ary = [12, 8, 24, 16, 1];
ary.insert();
console.log(ary);

Способ 4: быстрая сортировка

Array.prototype.quick = function quick() {
    // 4.结束递归(当数组中小于等于一项,则不用处理)
    if (this.length <= 1) {
        return this;
    }
    // 1.找到数组的中间项,在原有的数组中把它移除
    let middleIndex = Math.floor(this.length / 2);
    let middleValue = this.splice(middleIndex, 1)[0];
    // 2.准备左右两个数组,循环剩下数组中的每一项,比当前项小的放到左边数组中,反之放到右边数组中
    let aryLeft = [],
        aryRight = [];
    for (let i = 0; i < this.length; i++) {
        let item = this[i];
        item < middleValue ? aryLeft.push(item) : aryRight.push(item);
    }
    // 3.递归方式让左右两边的数组持续这样处理,一直到左右两边都排好序为止(最后让左边+中间+右边拼接成为最后的结果)
    return quick(aryLeft).concat(middleValue, quick(aryRight));
}
let ary = [12, 8, 15, 16, 1, 24];
ary.quick();
console.log(ary);

Метод 4: сортировка по холму

Array.prototype.shell = function shell() {
    let gap = Math.floor(this.length / 2);
    while (gap >= 1) {
        for (let i = gap; i < this.length; i++) {
            while (i - gap >= 0 && this[i] < this[i - gap]) {
                swap(this, i, i - gap);
                i = i - gap;
            }
        }
        gap = Math.floor(gap / 2);
    }
};
let arr = [58, 23, 67, 36, 40, 46, 35, 28, 20, 10];
arr.shell();
console.log(arr);

16. Максимальное/минимальное значение в массиве

Три основных способа получить максимальное/минимальное значение в массиве

Способ 1: на основе сортировки

ary.sort(function (a, b) {
	return a - b;
});
let min = ary[0];
let max = ary[ary.length - 1];
console.log(min, max);

Способ 2: Используйте Math.min/max

let min = Math.min(...ary);
console.log(min);
//==========================
let min = Math.min.apply(null,ary);
console.log(min);

Метод 3: Гипотетический метод

let max = ary[0];
for (let i = 1; i < ary.length; i++) {
	let item = ary[i];
	item > max ? max = item : null;
}
//=> for 循环 也可以改写为 forEach
ary.forEach(item => {
	item > max ? max = item : null;
});
console.log(max); 

17. Получить смещение элемента к BODY

function offset(element) {
    let parent = element.offsetParent,
        top = element.offsetTop,
        left = element.offsetLeft;
    while (parent) {
        if (!/MSIE 8/.test(navigator.userAgent)) {
            left += parent.clientLeft;
            top += parent.clientTop;
        }
        left += parent.offsetLeft;
        top += parent.offsetTop;
        parent = parent.offsetParent;
    }
    return {
        top,
        left
    };
}

18. Получите и установите стили CSS

/* 获取CSS样式 */
function getCss(element, attr) {
    let value = window.getComputedStyle(element)[attr],
        reg = /^\d+(px|rem|em)?$/i;
    if (reg.test(value)) {
        value = parseFloat(value);
    }
    return value;
}
/* 设置CSS样式:单个设置 */
function setCss(element, attr, value) {
    if (attr === "opacity") {
        element['style']['opacity'] = value;
        element['style']['filter'] = `alpha(opacity=${value*100})`;
        return;
    }
    let reg = /^(width|height|margin|padding)?(top|left|bottom|right)?$/i;
    if (reg.test(attr)) {

        if (!isNaN(value)) {
            value += 'px';
        }
    }
    element['style'][attr] = value;
}
/* 设置CSS样式:对象形式设置 */
function setGroupCss(element, options) {
    for (let key in options) {
        if (!options.hasOwnProperty(key)) break;
        setCss(element, key, options[key]);
    }
}

function css(element) {
    let len = arguments.length,
        attr = arguments[1],
        value = arguments[2];
    if (len >= 3) {
        // 单一设置样式
        setCss(element, attr, value);
        return;
    }
    if (attr !== null && typeof attr === "object") {
        // 批量设置
        setGroupCss(element, attr);
        return;
    }
    // 获取样式
    return getCss(element, attr);
}

Сегодняшний контент будет здесь первым.Я изначально хотел поместить часть исходного кода, который я прочесал, но, учитывая, что куча кода достаточно скучна, если длина слишком велика, я боюсь, что Сяо Сезам не сможет прочитать это сама 😓 ;

В то же время вы также можете предоставить новые идеи и некоторые часто используемые методы, Сяо Сезам благодарен 🙏 😄