"Не бойся, не обращай внимания, работай впредь" - Всем привет! Я Маленький Сезам 😄
Титульная вечеринка, она снова, снова, снова...
Эта статья представляет собой сводку всех 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. Глубокий клон
метод первый:
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);
}
Сегодняшний контент будет здесь первым.Я изначально хотел поместить часть исходного кода, который я прочесал, но, учитывая, что куча кода достаточно скучна, если длина слишком велика, я боюсь, что Сяо Сезам не сможет прочитать это сама 😓 ;
В то же время вы также можете предоставить новые идеи и некоторые часто используемые методы, Сяо Сезам благодарен 🙏 😄