
Daha yüksek dereceli fonksiyonlar tartışmasız JavaScript dilinde şimdiye kadar olan en iyi şeylerden biridir. İyi nedenlerle yaygın olarak kullanılıyorlar!
Daha yüksek mertebeden bir fonksiyonun ne olduğunu bilmiyorsanız, bunlar basitçe diğer fonksiyonları argüman olarak alan fonksiyonlar veya sonuç olarak bir fonksiyon döndüren fonksiyonlardır.
JavaScript’te yeniyken, bunların ne olduğunu anlamam biraz zaman aldı, bu yüzden bu pozisyondaysanız, umarım bu gönderiyi okuduktan sonra onları daha net anlamış olursunuz.
Bununla birlikte, Daha İyi Anlama için JavaScript’te 5 Yüksek Dereceli İşlev Örneği:
1. .map
, .forEach
vb.
JavaScript’te yalnızca bir günlüğüne bile yeniyseniz, büyük olasılıkla aşağıdaki gibi yerel JavaScript dizisi yöntemleri aracılığıyla daha yüksek dereceli işlevlerle çalışıyorsunuzdur: .map
.
Aşağıdaki pasaj bir dizi üzerinde döner ve bir işlevi çağırır son öğeye ulaşana kadar her öğe üzerinde. yeteneği çağırabileceği bir işlev alarak onu daha yüksek dereceli bir işlev yapan şeydir:
function prefixWordWithUnderscore(word) {
return `_${word}`
}
const words = ['coffee', 'apple', 'orange', 'phone', 'starbucks']
const prefixedWords = words.map(prefixWordWithUnderscore)
2. Bir işlemin birden çok varyasyonunu desteklemek için daha yüksek dereceli işlevlerin kullanılması
Bazen daha yüksek dereceli bir işlev oluşturmaya karar verebiliriz. böylece daha fazla varyasyon oluşturmak için kullanabiliriz istenen bir işlemin
Aşağıdaki örnekte, temel bir utilizePrefixer
işlevi, alan bir işlevi döndüren daha yüksek dereceli bir işlevdir. word
argüman olarak ve öneki döndürülen değere uygular.
function utilizePrefixer(prefix) {
return function(word) {
return `${prefix}${word}`
}
}
const withMoneySign = utilizePrefixer('$')
const withCompanyName = utilizePrefixer('Fandango')
const tenDollars = withMoneySign('9.99')
const formHeader = withCompanyName(
' is the company you will be applying for today',
)
console.log(tenDollars)
console.log(formHeader)
3. Kontrolün tersine çevrilmesi
Bir işleve işaret eden bir grup kodu yeniden düzenlemeniz gereken bir durumda olduğunuzda, kodunuzun geçtiği yönü tersine çevirebilecek gelişmiş bir işlev oluşturabilirsiniz.
Eski bir gönderiden bir örnek kopyalayıp yapıştıracağım çünkü bu, bu noktayı anlamak için sağlam bir örnek:
Önceki işimde kullandık tepki vermek Bildirimleri görüntülemek için biz onu kullandık her yerde. Ayrıca, hızlı son dakika UX kararları için harika kaçış kapakları da yaparlar: “Bu hatayı nasıl ele almalıyız? Sadece bir kadeh kaldırma bildirimi göster!” Tamamlandı.
Ancak, uygulama büyüdükçe ve karmaşıklık düzeyi üstümüze gelmeye başladığında, bildirimlerimizin çok sık olmaya başladığını fark etmeye başladık. Bu iyi, ancak yinelemeleri önlemenin bir yolu yoktu. Bu, bazı tost bildirimlerinin, açık olduklarında bile ekranda birden çok kez göründüğü anlamına geliyordu. tam olarak aynı üstündeki tost gibi.
Böylece, aktif tost bildirimlerinin kaldırılmasına yardımcı olmak için kitaplığın sağladığı API’den yararlandık. İD kullanarak tost.dismiss().
Önümüzdeki kısımları açıklamak için, devam etmeden önce tostları içe aktardığımız dosyayı göstermek iyi bir fikir olabilir:
import React from 'react'
import { GoCheck, GoAlert } from 'react-icons/go'
import { FaInfoCircle } from 'react-icons/fa'
import { MdPriorityHigh } from 'react-icons/md'
import { toast } from 'react-toastify'
export const toastIds = {
internetOnline: 'internet-online',
internetOffline: 'internet-offline',
retryInternet: 'internet-retry',
}
const getDefaultOptions = (options) => ({
position: toast && toast.POSITION.BOTTOM_RIGHT,
...options,
})
const Toast = ({ children, success, error, info, warning }) => {
let componentChildren
if (!React.isValidElement(children) && typeof children !== 'string') {
componentChildren = 'An error occurred'
} else {
componentChildren = children
}
let Icon = GoAlert
if (success) Icon = GoCheck
if (error) Icon = GoAlert
if (info) Icon = FaInfoCircle
if (warning) Icon = MdPriorityHigh
return (
<div style={{ paddingLeft: 10, display: 'flex', alignItems: 'center' }}>
<div style={{ width: 30, height: 30 }}>
<Icon style={{ color: '#fff', width: 30, height: 30 }} />
</div>
<div style={{ padding: 8, display: 'flex', alignItems: 'center' }}>
<span style={{ color: '#fff' }}>{componentChildren}</span>
</div>
</div>
)
}
export const success = (msg, opts) => {
return toast.success(<Toast success>{msg}</Toast>, {
className: 'toast-success',
...getDefaultOptions(),
...opts,
})
}
export const error = (msg, opts) => {
return toast.error(<Toast error>{msg}</Toast>, {
className: 'toast-error',
...getDefaultOptions(),
...opts,
})
}
export const info = (msg, opts) => {
return toast.info(<Toast info>{msg}</Toast>, {
className: 'toast-info',
...getDefaultOptions(),
...opts,
})
}
export const warn = (msg, opts) => {
return toast.warn(<Toast warning>{msg}</Toast>, {
className: 'toast-warn',
...getDefaultOptions(),
...opts,
})
}
export const neutral = (msg, opts) => {
return toast(<Toast warning>{msg}</Toast>, {
className: 'toast-default',
...getDefaultOptions(),
...opts,
})
}
Şimdi sabredin, bunun çekici görünmeyebileceğini biliyorum. Ama söz veriyorum iki dakika içinde daha iyi olacak.
Ekranda önceden bir tost olup olmadığını kontrol etmek için ayrı bir bileşende sahip olduğumuz şey buydu. Ve varsa, o tostu kaldırmaya ve yeni tostu yeniden görüntülemeye çalışacaktır.
import { toast } from 'react-toastify'
import {
info as toastInfo,
success as toastSuccess,
toastIds,
} from 'util/toast'
const onOnline = () => {
if (toast.isActive(toastIds.internetOffline)) {
toast.dismiss(toastIds.internetOffline)
}
if (toast.isActive(toastIds.retryInternet)) {
toast.dismiss(toastIds.retryInternet)
}
if (!toast.isActive(toastIds.internetOnline)) {
toastSuccess('You are now reconnected to the internet.', {
position: 'bottom-center',
toastId: toastIds.internetOnline,
})
}
}
const onOffline = () => {
if (!toast.isActive(toastIds.internetOffline)) {
toastInfo('You are disconnected from the internet right now.', {
position: 'bottom-center',
autoClose: false,
toastId: toastIds.internetOffline,
})
}
}
useInternet({ onOnline, onOffline })
return <App />
Bu iyi çalışıyordu – ancak, uygulama boyunca aynı şekilde değiştirilmesi gereken başka tostlarımız vardı. Yinelenenleri kaldırmak için bir tost bildirimi görüntüleyen her dosyayı gözden geçirmemiz gerekiyordu.
düşündüğümüzde her dosyadan geçiyor 2019’da bunun çözüm olmadığını hemen anladık. biz de baktık util/toast.js
dosya ve bunun yerine sorunumuzu çözmek için yeniden düzenledi. İşte daha sonra nasıl göründüğü:
src/util/toast.js
import React, { isValidElement } from 'react'
import isString from 'lodash/isString'
import isFunction from 'lodash/isFunction'
import { GoCheck, GoAlert } from 'react-icons/go'
import { FaInfoCircle } from 'react-icons/fa'
import { MdPriorityHigh } from 'react-icons/md'
import { toast } from 'react-toastify'
export const toastIds = {
internetOnline: 'internet-online',
internetOffline: 'internet-offline',
retryInternet: 'internet-retry',
}
const getDefaultOptions = (options) => ({
position: toast && toast.POSITION.BOTTOM_RIGHT,
...options,
})
const Toast = ({ children, success, error, info, warning }) => {
let componentChildren
if (!isValidElement(children) && !isString(children)) {
componentChildren = 'An error occurred'
} else {
componentChildren = children
}
let Icon = GoAlert
if (success) Icon = GoCheck
if (error) Icon = GoAlert
if (info) Icon = FaInfoCircle
if (warning) Icon = MdPriorityHigh
return (
<div style={{ paddingLeft: 10, display: 'flex', alignItems: 'center' }}>
<div style={{ width: 30, height: 30 }}>
<Icon style={{ color: '#fff', width: 30, height: 30 }} />
</div>
<div style={{ padding: 8, display: 'flex', alignItems: 'center' }}>
<span style={{ color: '#fff' }}>{componentChildren}</span>
</div>
</div>
)
}
const toaster = (function() {
const ensurePreviousToastIsRemoved = (toastId) => {
if (toastId) {
if (toast.isActive(toastId)) {
toast.dismiss(toastId)
}
}
}
const attemptGetToastId = (msg, opts) => {
let toastId
if (opts && isString(opts.toastId)) {
toastId = opts.toastId
} else if (isString(msg)) {
toastId = msg
}
return toastId
}
const handleToast = (type) => (msg, opts) => {
const toastFn = toast[type]
if (isFunction(toastFn)) {
const toastProps = {}
let className = ''
const additionalOptions = {}
const toastId = attemptGetToastId(msg, opts)
if (toastId) additionalOptions.toastId = toastId
ensurePreviousToastIsRemoved(toastId)
switch (type) {
case 'success':
toastProps.success = true
className = 'toast-success'
break
case 'error':
toastProps.error = true
className = 'toast-error'
break
case 'info':
toastProps.info = true
className = 'toast-info'
break
case 'warn':
toastProps.warning = true
className - 'toast-warn'
break
case 'neutral':
toastProps.warning = true
className - 'toast-default'
break
default:
className = 'toast-default'
break
}
toastFn(<Toast {...toastProps}>{msg}</Toast>, {
className,
...getDefaultOptions(),
...opts,
...additionalOptions,
})
}
}
return {
success: handleToast('success'),
error: handleToast('error'),
info: handleToast('info'),
warn: handleToast('warn'),
neutral: handleToast('neutral'),
}
})()
export const success = toaster.success
export const error = toaster.error
export const info = toaster.info
export const warn = toaster.warn
export const neutral = toaster.neutral
Her dosyayı gözden geçirmek yerine, en basit çözüm bir dosya oluşturmaktı. üst düzey fonksiyon. Bunu yapmak, rolleri “ters çevirmemize” izin verdi, böylece dosyalar arasında arama yapmak yerine, tostlar üst düzey fonksiyonumuza yönelik.
Bu şekilde dosyalardaki kodlar olumsuzluk değiştirilmiş veya dokundu. Hala normal çalışıyorlar ve sonunda gereksiz kod yazmak için hiçbir yere gitmeden yinelenen tostları kaldırma yeteneği kazandık. Bu zaman tasarrufu.
4. Beste yapmak
Daha yüksek dereceli işlevler, onları oluşturmaya başladığınızda çok daha fazla parlamaya başlar. Kişi birçok nedenden dolayı beste yapmayı seçebilir. Aşağıdaki örnek için, JavaScript’in her biri için kurbağa dizisi üzerinde tekrar tekrar dolaşmasını önlemek istediğimiz için oluşturuyoruz. .filter
operasyon:
function createFilterers() {
const _filters = {
ids: [],
fns: {},
}
return {
addFilter(name, fn) {
_filters.ids.push(name)
_filters.fns[name] = fn
},
removeFilter(name) {
const index = _filters.ids.indexOf(name)
if (index !== -1) _filters.splice(index, 1)
delete _filters.fns[name]
},
filter(arr) {
const filters = _filters.ids.map((id) => _filters.fns[id])
return arr.reduce((acc, item) => {
for (let index = 0; index < _filters.ids.length; index++) {
const id = _filters.ids[index]
const filter = _filters.fns[id]
if (!filter(item)) {
return acc
}
}
return acc.concat(item)
}, [])
},
}
}
const frogs = [
{
name: 'bobTheFrog',
age: 2,
gender: 'male',
favoriteFood: 'fly',
weight: 5,
},
{
name: 'lisaTheFrog',
age: 3,
gender: 'female',
favoriteFood: 'fly',
weight: 1,
},
{
name: 'sallyTheFrog',
age: 10,
gender: 'female',
favoriteFood: 'caterpillar',
weight: 20,
},
{
name: 'mikeTheFrog',
age: 1,
gender: 'male',
favoriteFood: 'worm',
weight: 8,
},
{
name: 'georgeTheFrog',
age: 7,
gender: 'male',
favoriteFood: 'fly',
weight: 28,
},
{
name: 'kellyTheFrog',
age: 3,
gender: 'female',
favoriteFood: 'ladybug',
weight: 3,
},
]
const filterer = createFilterers()
filterer.addFilter('fat-frogs', (frog) => {
return frog.weight >= 8
})
filterer.addFilter('male-frogs', (frog) => {
return frog.gender === 'male'
})
const filteredFrogs = filterer.filter(frogs)
console.log(filteredFrogs)
Bu, uygulamamızın her yerinde bunun gibi tekrarlayan kodlar yazmamızı engelleyebilir:
const filteredFrogs = frogs
.filter((frog) => {
return frog.weight >= 8
})
.filter((frog) => {
return frog.gender === 'male'
})
.filter((frog) => {
return frog.name.startsWith('b')
})
5. Dahili durum
Daha yüksek dereceli bir işlev oluşturduğumuzda, kapsam içinde bazı yerel durumlar da oluşturabileceğimizi ve gelecekteki işlemler için önbelleğe alınacağını belirtmekte fayda var:
function createMyHigherOrderFunction(options) {
const state = { ...options }
return function(...args) {
return function(callback) {
return callback(state, ...args)
}
}
}
const prepare = createMyHigherOrderFunction({
name: 'bobby',
favoriteFood: 'steak',
})
const prepareWithArgs = prepare({ country: 'United States' })
const finalize = prepareWithArgs((state, options) => ({ ...state, ...options }))
console.log(finalize)