- Автор: Чен Даютоу
- гитхаб:KRISACHAN
Хотя сегодня, в 2020 году, существуют различные интерфейсные фреймворки и инструменты, и эти фреймворки и инструменты также помогли нам заранее решить многие неприятные проблемы, но инструменты всегда остаются инструментами, а твердые базовые навыки являются ядром. несколько Фактический фрагмент кода для улучшения кодирования нашего родного JS.
Определить тип данных
Сначала зададим вопрос:typeof
Правильно ли определить тип?
Ответ: нет, потому что по историческим причинам при оценке примитивных типовtypeof null
будет равноobject
. А для объектов, кроме функций, они будут преобразованы вobject
. Примеры следующие:
typeof 1 // 'number'
typeof "1" // 'string'
typeof null //
typeof [] // 'object'
typeof {} // 'object'
typeof window.alert // 'function'
Еще один вопрос,instanceof
Правильно ли определить тип?
Ответ: все еще невозможно, хотяinstanceof
Судится по цепочке прототипов, но для объектов,Array
также будет преобразовано вObject
, а также не может различать примитивные типыstring
иboolean
. Например:
function Func() {}
const func = new Func()
console.log(func instanceof Func) // true
const obj = {}
const arr = []
obj instanceof Object // true
arr instanceof Object // true
arr instanceof Array // true
const str = "abc"
const str2 = new String("abc")
str instanceof String // false
str2 instanceof String // true
Так что делать?
На данный момент мы можем использовать:Object.prototype.toString.call()
Так почему?
потому что каждый объект имеетtoString()
метод, который автоматически вызывается, когда объект должен быть представлен в виде текстового значения или для ссылки на объект в виде ожидаемой строки. По умолчанию изObject
Каждый производный объект наследуетtoString()
метод. Если этот метод не переопределен в пользовательском объекте, тоtoString()
возвращение[Object type]
,вtype
является типом объекта. Итак, есть следующие примеры:
Object.prototype.toString.call(new Date()) // [object Date]
Object.prototype.toString.call("1") // [object String]
Object.prototype.toString.call(1) // [object Numer]
Object.prototype.toString.call(undefined) // [object Undefined]
Object.prototype.toString.call(null) // [object Null]
Таким образом, объединяя вышеуказанные точки знаний, мы можем инкапсулировать следующие общие методы оценки типов:
var type = function(data) {
var toString = Object.prototype.toString;
var dataType =
data instanceof Element
? "element" // 为了统一DOM节点类型输出
: toString
.call(data)
.replace(/\[object\s(.+)\]/, "$1")
.toLowerCase()
return dataType
};
Способ применения следующий:
type("a") // string
type(1) // number
type(window) // window
type(document.querySelector("h1")) // element
Универсальная инкапсуляция массива/подобного массиву объекта
Если мы используем API-интерфейс массива ES5/ES6+, легко выполнять различные циклические операции над массивом, но что, если мы хотим зациклить объект, подобный массиву?
НапримерNodeList
. Прямой цикл сообщит об ошибке:
document.querySelectorAll("div").map(e => e) // Uncaught TypeError: document.querySelectorAll(...).map is not a function
Конечно, мы можем использовать оператор распространения:
[...document.querySelectorAll("div")].map(e => e)
Что, если мы не будем использовать оператор спреда?
тогда мы можем использоватьcall
характеристики, воляNodeList
Элементы вставляются в массив один за другим, например:
var listMap = function(array, type, fn) {
return !fn ? array : Array.prototype[type]["call"](array, fn)
};
Способ применения следующий:
var divs = document.querySelectorAll("div");
listMap(divs, "forEach", function(e) {
console.log(e)
});
Получить смещение узла элемента dom
если используетсяjQuery
детская обувь, которую вы никогда не забудете$('').offset()
Сила этого API заключается в том, что этот API может легко получить смещение элемента, поэтому, если мы не используемjQuery
Как этого добиться?
Сначала рассмотрим пример:
var getOffset = function(el) {
var scrollTop =
el.getBoundingClientRect().top +
document.body.scrollTop +
document.documentElement.scrollTop;
var scrollLeft =
el.getBoundingClientRect().left +
document.body.scrollLeft +
document.documentElement.scrollLeft;
return {
top: scrollTop,
left: scrollLeft
}
}
Сначала давайте посмотрим наgetBoundingClientRect()
Сюда.
getBoundingClientRect()
Метод возвращает размер элемента и его положение относительно области просмотра. Возвращаемое значение представляет собойDOMRect
объект, который представляет собой набор границ CSS, связанных с этим элементом.
Тогда естьdocument.body.scrollTop
иdocument.documentElement.scrollTop
Это две одинаковые функции, но одна из них всегда будет равна 0 в разных браузерах, поэтому выполняется описанная выше обработка совместимости. Поэтому, когда мы выполняем функцию перетаскивания, мы можем полагаться на вышеуказанные свойства.
Способ применения следующий:
var el = document.querySelector(".moveBox")
getOffset(el) // {top: xxx, left: xxx}
Мы можем видеть вышеупомянутый эффект джойстика, вот его использованиеoffset()
Делайте позиционные суждения. Конкретный код реализации можно увидеть:код спрей.IO/Антияпонское производство 77/…
Эффекты затухания
// Fade in
var fadeIn = function (el) {
el.style.opacity = 0
var last = +new Date()
var tick = function() {
el.style.opacity = +el.style.opacity + (new Date() - last) / 400
last = +new Date()
if (+el.style.opacity < 1) {
requestAnimationFrame(tick))
}
}
tick()
}
// Fade out
var fadeOut = function (el) {
el.style.opacity = 1
var last = +new Date()
var tick = function() {
el.style.opacity = +el.style.opacity - (new Date() - last) / 400
last = +new Date()
if (+el.style.opacity > 0) {
requestAnimationFrame(tick)
}
}
tick()
}
Выше приведена конкретная реализация эффекта постепенного появления и исчезновения, здесь используетсяrequestAnimationFrame
правильноopacity
Модификации производятся рекурсивно.
На самом деле, здесь необходимо упомянуть понятие, т.разрезание времени.
Это очень важное понятие, т.ReactизFiberОсновная реализацияразрезание времени. Он разделит длинную задачу на очередь задач, содержащую несколько небольших задач, а затем выполнит их одну за другой.
requestAnimationFrame
Это такой API.Он может определять время выполнения callback-функции в соответствии с системой.По сути, это обновление кадра анимации перед следующей перерисовкой.Благодаря этому механизму он может предотвратить потерю кадров.
Манипулирование данными с использованием концепции очередей
Очередь — это линейная таблица в порядке поступления (FIFO, First-In-First-Out). В конкретных приложениях это обычно реализуется с помощью связанного списка или массива. Очередь допускает только операции вставки на заднем конце (называемые задними) и операции удаления на переднем конце (называемые передними).
Хотя многие люди думают, что понимание структуры данных мало влияет на внешний интерфейс, если мы понимаем некоторые основные концепции, можем ли мы расширить наше мышление при кодировании? Давайте посмотрим на следующие два примера:
Получите координаты узла под этим родительским узлом.
Если мы хотим работать с нативным DOM, то мы не можем обойти функцию получения индекса узла в родительском узле, так как же нам этого добиться?
Конечно, мы используем наш цикл для обхода набора подэлементов, пока не будет определен индекс Код выглядит следующим образом:
var index = function(el) {
if (!el) {
return -1
}
var i = 0
while ((el = el.previousElementSibling)) {
i++
}
return i
}
очистить дочерние узлы
Если мы хотим очистить дочерние элементы узла DOM, у нас есть следующие методы:
var empty = function(el) {
while (el.firstChild) {
el.removeChild(el.firstChild);
}
}
Вышесказанное просто для того, чтобы дать представление, на самом делеel.innerHTML = ''
было бы лаконичнее.
Оптимизация данных с уменьшением
Дедупликация массива
Правильно, это еще одна распространенная проблема, дедупликация массивов, но на этот раз мы удаляем не просто один кусок данных, а набор объектов с одинаковым значением ключа. Например, в следующем примере у нас есть следующие данные:
круто уменьшить
дедупликация данных
Сначала давайте рассмотрим старомодный вопрос Предположим, что у нас есть такой объект:
const data = [
{
name: "Kris",
age: "24"
},
{
name: "Andy",
age: "25"
},
{
name: "Kitty",
age: "25"
},
{
name: "Andy",
age: "25"
},
{
name: "Kitty",
age: "25"
},
{
name: "Andy",
age: "25"
},
{
name: "Kitty",
age: "25"
}
]
Теперь мы собираемся вернуться внутрьname
Повторяющиеся объекты, на этот раз мы можем использоватьreduce
, пример следующий:
const dataReducer = (prev, cur, idx) => {
let obj = {}
const { name } = cur
obj[name] = cur
return {
...prev,
...obj
}
}
const reducedData = data.reduce(dataReducer, {});
let newData = Object.values(reducedData);
Создание элементов объекта в пакетах
В реальном бизнесе fishhead есть операция, которая должна работать с такими объектами, как следующие:
{
a1: 'data',
a2: 'data',
...,
an: 'data'
}
Такая ленивая рыба, как я, по одной писать точно не будет, поэтому есть следующие способы
const createList = (item, idx) => {
let obj = {}
obj[`a${idx}`] = "data"
return obj
}
const listReducer = (acc, cur) => (!acc ? { ...cur } : { ...cur, ...acc })
const obj = Array.from(new Array(20), createList).reduce(listReducer)
Если вам нравится обсуждать технологии или у вас есть какие-либо комментарии или предложения по этой статье, вы можете добавить друзей Yutou в WeChat для совместного обсуждения.Конечно, Yutou также надеется поговорить с вами о жизни, хобби и поболтать. WeChat ID Fish Head: krisChans95 Вы также можете отсканировать код, чтобы подписаться на официальный аккаунт и подписаться на более интересный контент.