Так называемое отсутствие правил и отсутствие кругов, время переднего плана в ходе групповой проверки кода показало, что код, написанный разными разработчиками в разные периоды, можно охарактеризовать как различающийся. Поэтому мы выдвинули некоторые соответствующие спецификации кода, надеясь в будущем сформировать стандарты кодирования команды.
В этой статье в основном оптимизируется некоторый JavaScript, чтобы сделать его более надежным, читабельным и удобным в сопровождении.
адрес гитхаба:GitHub.com/Майкл-Ли Чжиган…
Предыдущий:спецификация кода внешнего интерфейса code-review
Оптимизация решения if
Условные операторы JavaScript неизбежно используются в нашей повседневной разработке, но часто наш код написан не очень хорошо, серияif-else
Или несколько вложенных суждений сделают код очень раздутым.Следующие примеры оптимизированы.
Спрос: в настоящее время существует 4 продукта, а именно мобильные телефоны, компьютеры, телевизоры и игровые приставки.Конечно, цены на каждый продукт разные.
1. Самый простой способ: если судить
let commodity = {
phone: '手机',
computer: '电脑',
television: '电视',
gameBoy: '游戏机',
}
function price(name) {
if (name === commodity.phone) {
console.log(1999)
} else if (name === commodity.computer) {
console.log(9999)
} else if (name === commodity.television) {
console.log(2999)
} else if (name === commodity.gameBoy) {
console.log(3999)
}
}
price('手机') // 9999
Недостатки: код слишком длинный, обслуживание и чтение неудобны.
2. Лучший способ:Switch
let commodity = {
phone: '手机',
computer: '电脑',
television: '电视',
gameBoy: '游戏机',
}
const price = (name) => {
switch (name) {
case commodity.phone:
console.log(1999)
break
case commodity.computer:
console.log(9999)
break
case commodity.television:
console.log(2999)
break
case commodity.gameBoy:
console.log(3999)
break
}
}
price('手机') // 9999
3. Лучший подход: шаблон стратегии
В шаблоне стратегии используются методы и идеи, такие как композиция, делегирование и полиморфизм, которые позволяют эффективно избежать множественных операторов условного выбора. Он обеспечивает идеальную поддержку принципа открытого-закрытого, инкапсулируя алгоритмы в отдельные стратегии, что упрощает их переключение, понимание и расширение.
const commodity = new Map([
['phone', 1999],
['computer', 9999],
['television', 2999],
['gameBoy', 3999],
])
const price = (name) => {
return commodity.get(name)
}
price('phone') // 1999
Оптимизация включений
includes
— это новый API в ES7, такой же, какindexOf
разница в томincludes
возвращается напрямуюBoolean
стоимость,indexOf
Затем возвращаемое значение индекса, как массив, так и строка, имеютincludes
метод.
Требование: давайте реализуем метод аутентификации личности и возвращаем соответствующий результат проверки, передавая идентификатор личности.
традиционный метод
function verifyIdentity(identityId) {
if (identityId == 1 || identityId == 2 || identityId == 3 || identityId == 4) {
return '你的身份合法,请通行!'
} else {
return '你的身份不合法'
}
}
includes
оптимизация
function verifyIdentity(identityId) {
if ([1, 2, 3, 4].includes(identityId)) {
return '你的身份合法,请通行!'
} else {
return '你的身份不合法'
}
}
для цикла
В JavaScript мы можем использоватьfor()
,while()
,for(in)
,for(of)
Несколько видов петель, собственно, среди этих трех петельfor(in)
крайне неэффективен, потому что ему нужно запрашивать хэш-ключ, поэтому его следует использовать как можно реже.
Наиболее традиционным оператором является цикл for, который работает с массивом с переменной i в качестве индекса, чтобы отслеживать, где к нему обращались.
var arr = ['a', 'b', 'c']
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]) //结果依次a,b,c
}
У вышеуказанного метода есть проблема: когда длина массива достигает миллионов,arr.length
Это должно быть вычислено миллион раз, что довольно интенсивно. Поэтому для его улучшения можно использовать следующие методы.
var arr = ['a', 'b', 'c']
for (var i = 0, length = arr.length; i < length; i++) {
console.log(arr[i]) //结果依次a,b,c
}
В настоящее времяarr.length
Его нужно рассчитать только один раз, оптимизируя производительность.
for-in
Обычно используется для обхода свойств объектов, но свойства необходимоenumerable
(перечислимое) для чтения. в то же времяfor-in
Вы также можете пройти массив. При пересечении массива он проходит подпрыренное значение массива.
var obj = { 0: 'a', 1: 'b', 2: 'c' }
for (var key in obj) {
console.log(key) //结果为依次为0,1,2
}
var arr = ['a', 'b', 'c']
for (var key in a) {
console.log(key) //结果为依次为0,1,2
}
for-of
Предложение выглядит немного похожеfor-in
заявление, но иfor-of
Отличие оператора в том, что он не может перебирать объекты, а только массивы.
var arr = ['a', 'b', 'c']
for (var value of arr) {
console.log(value) // 结果依次为a,b,c
}
for-of
Сравниватьfor-in
Лучше зациклиться на массиве.for-of
пока естьIterator
Структура данных интерфейса может использоваться для перебора его членов. Он напрямую считывает значение ключа.for-in
Все свойства объекта, которые должны быть исчерпаны, включая пользовательские добавленные свойства, также могут быть пройдены. а такжеfor-in
изkey
даString
Типа, идет процесс конвертации, накладные расходы относительно большие.
Поэтому старайтесь избегать использования циклических массивов в процессе разработки.for-in
.
Дедупликация массива
Дедупликация массива часто встречается при реальной разработке и обработке данных, методов много, и я не буду перечислять их здесь по одному.
1. Самый традиционный способ: с помощью массиваindexOf
Подпишите свойства для запроса.
function unique4(arr) {
var newArr = []
for (var i = 0; i < arr.length; i++) {
if (newArr.indexOf(arr[i]) === -1) {
newArr.push(arr[i])
}
}
return newArr
}
console.log(unique4([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]))
// [1, 2, 3, 5, 6, 7, 4]
2. Оптимизация: использование ES6Set
метод.
Set
сам по себе является конструктором, используемым для генерацииSet
структура данных.Set
Функции могут принимать массив (или другую структуру данных с помощью интерфейса для инициализации) в качестве параметра для инициализации.Set
Объекты позволяют хранить значения любого типа, будь то примитивное значение или ссылка на объект. Он похож на массив, но значение члена уникально, нет повторяющихся значений.
function unique4(arr) {
return Array.from(new Set(arr)) // 利用Array.from将Set结构转换成数组
}
console.log(unique4([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]))
// [1, 2, 3, 5, 6, 7, 4]
стрелочная функция
Синтаксис выражений стрелочных функций более лаконичен, чем функциональных выражений. Поэтому в разработке более рекомендуется использовать стрелочные функции. особенно вvue
В проекте с помощью стрелочной функции не нужно обновлятьthis
Переназначить переменную.
// 使用functions
var arr = [5, 3, 2, 9, 1]
var arrFunc = arr.map(function (x) {
return x * x
})
console.log(arrFunc)
// 使用箭头函数
var arr = [5, 3, 2, 9, 1]
var arrFunc = arr.map((x) => x * x)
Обратите внимание, что стрелочные функции не связаныarguments
, вместоrest
Параметры... разрешены.
// 不能使用 arguments
let fun1 = (b) => {
console.log(arguments)
}
fun1(2, 92, 32, 32) // Uncaught ReferenceError: arguments is not defined
// 使用rest 参数
let fun2 = (...c) => {
console.log(c)
}
fun2(3, 82, 32, 11323) // [3, 82, 32, 11323]
Создание Дома
При создании нескольких элементов dom сначала размещайте элементыappend
прибытьDocumentFragment
, окончательное объединение будетDocumentFragment
добавил на страницу.
обычный метод;
for (var i = 0; i < 1000; i++) {
var el = document.createElement('p')
el.innerHTML = i
document.body.appendChild(el)
}
использоватьDocumentFragment
оптимизировать несколько разappend
var frag = document.createDocumentFragment()
for (var i = 0; i < 1000; i++) {
var el = document.createElement('p')
el.innerHTML = i
frag.appendChild(el)
}
document.body.appendChild(frag)
Лучший способ: использовать его один разinnerHTML
Назначайте задания вместо создания элементов dom
var html = []
for (var i = 0; i < 1000; i++) {
html.push('<p>' + i + '</p>')
}
document.body.innerHTML = html.join('')
утечка памяти
Память, которая больше не используется системными процессами и не освобождается вовремя, называется утечкой памяти. Когда использование памяти становится все выше и выше, это повлияет на производительность системы и приведет к сбою процесса.
Причины утечек памяти
глобальная переменная
1. Необъявленная переменная или использованиеthis
созданная переменная (this
указывает наwindow
) вызовет утечку памяти
function fn() {
a = "Actually, I'm a global variable"
}
fn()
function fn() {
this.a = "Actually, I'm a global variable"
}
fn()
Решение:
- Избегайте создания глобальных переменных
- Чтобы использовать строгий режим, добавьте заголовок файла JavaScript или в начало функции.
use strict
.
2. В одностраничном приложении vue объявленные глобальные переменные не очищаются при переключении страниц
<template>
<div id="home">
这里是首页
</div>
</template>
<script>
export default {
mounted() {
window.test = {
// 此处在全局window对象中引用了本页面的dom对象
name: 'home',
node: document.getElementById('home')
}
}
}
</script>
Решение: Удаляйте ссылку кстати, когда страница выгружается.
destroyed () {
window.test = null // 页面卸载的时候解除引用
}
Закрытие
Причины утечек памяти, вызванных замыканиями: замыкания могут поддерживать локальные переменные внутри функций, чтобы их нельзя было освободить.
function fn() {
var a = "I'm a"
return function () {
console.log(a)
}
}
Решение: Определите внешний обработчик событий, освободите замыкание или удалите ссылку на dom во внешней функции, где определен обработчик событий.
Таймер или прослушиватель событий
Потому что некоторые страницы в проекте неизбежно будут столкнуться с таймерами или мониторинга событий. Однако при выходе из текущей страницы, если таймер не очищается во времени и разумно, он приведет к тому времени бизнес-логики или даже приложение. В это время необходимо очистить слушатель мероприятия таймера, то есть жизненный цикл Функция разгрузки страницы (закрытие). Очистить таймер.
methods:{
resizeFun () {
this.tableHeight = window.innerHeight - document.getElementById('table').offsetTop - 128
},
setTimer() {
this.timer = setInterval(() => { })
},
clearTimer() {//清除定时器
clearInterval(this.timer)
this.timer = null
}
},
mounted() {
this.setTimer()
window.addEventListener('resize', this.resizeFun)
},
beforeDestroy() {
window.removeEventListener('resize', this.resizeFun)
this.clearTimer()
}
Защита от тряски и дросселирования
В процессе фронтенд-разработки нам часто приходится привязывать какие-то постоянно срабатывающие события, напримерresize
,scroll
,mousemove
И так далее, но иногда мы не хотим выполнять функцию так часто, как событие продолжает срабатывать. В это время используются анти-шейк и троттлинг.
Случай 1: При удаленном поиске необходимо динамически получать данные через интерфейс.Если интерфейс запрашивается для каждого пользовательского ввода, это пустая трата полосы пропускания и производительности.
<Select :remote-method="remoteMethod">
<Option v-for="item in temoteList" :value="item.value" :key="item.id">{{item.label}}</Option>
</Select>
<script>
function debounce(fn, wait) {
let timeout = null
return function () {
if (timeout !== null) clearTimeout(timeout)
timeout = setTimeout(fn, wait)
}
}
export default {
methods:{
remoteMethod:debounce(function (query) {
// to do ...
}, 200),
}
}
<script>
Случай 2: непрерывный запускscroll
событие, не выполненное немедленноhandle
функция, если не срабатывает в течение 1000 мсscroll
Когда происходит событие, оно будет запущено один раз с задержкойhandle
функция.
function debounce(fn, wait) {
let timeout = null
return function () {
if (timeout !== null) clearTimeout(timeout)
timeout = setTimeout(fn, wait)
}
}
function handle() {
console.log(Math.random())
}
window.addEventListener('scroll', debounce(handle, 1000))
загружать js асинхронно
По умолчанию браузер загружает js-скрипт синхронно, при разборе html встречается<script>
Метка остановится, и после того, как скрипт будет загружен, проанализирован и выполнен, он продолжит анализ и рендеринг вниз.
Если размер js-файла относительно большой, время загрузки будет очень долгим, что легко приведет к блокировке браузера, а на странице браузера будет отображаться эффект «белого экрана», и пользователь почувствует, что браузер "завис" и не отвечает. На этом этапе мы можем позволить скрипту js загружаться и выполняться асинхронно.
<script src="path/to/home.js" defer></script>
<script src="path/to/home.js" async></script>
В приведенном выше коде<script>
Этикеткиdefer
а такжеasync
properties, когда браузер распознает эти два свойства, js будет загружаться асинхронно. То есть браузер не будет ждать, пока скрипт будет загружен и выполнен, прежде чем выполнять его в обратном направлении, а продолжит выполняться в обратном направлении напрямую.
Разница между отсрочкой и асинхронностью:
- defer: структура DOM полностью генерируется, и другие скрипты выполняются до их выполнения (визуализируются, а затем выполняются). иметь более одного
defer
Когда скрипт будет выполнен, он будет загружен и выполнен в том порядке, в котором появляются страницы. - async: после завершения загрузки механизм рендеринга прервет рендеринг и после выполнения этого скрипта продолжит рендеринг (выполнить после загрузки). иметь более одного
async
При написании сценариев нет гарантии, что страницы будут загружаться и выполняться в том порядке, в котором они появляются.