Так называемое отсутствие правил и отсутствие кругов, время переднего плана в ходе групповой проверки кода показало, что код, написанный разными разработчиками в разные периоды, можно охарактеризовать как различающийся. Поэтому мы выдвинули некоторые соответствующие спецификации кода, надеясь в будущем сформировать стандарты кодирования команды.
В этой статье в основном оптимизируется некоторый 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а такжеasyncproperties, когда браузер распознает эти два свойства, js будет загружаться асинхронно. То есть браузер не будет ждать, пока скрипт будет загружен и выполнен, прежде чем выполнять его в обратном направлении, а продолжит выполняться в обратном направлении напрямую.
Разница между отсрочкой и асинхронностью:
- defer: структура DOM полностью генерируется, и другие скрипты выполняются до их выполнения (визуализируются, а затем выполняются). иметь более одного
deferКогда скрипт будет выполнен, он будет загружен и выполнен в том порядке, в котором появляются страницы. - async: после завершения загрузки механизм рендеринга прервет рендеринг и после выполнения этого скрипта продолжит рендеринг (выполнить после загрузки). иметь более одного
asyncПри написании сценариев нет гарантии, что страницы будут загружаться и выполняться в том порядке, в котором они появляются.