Daha İyi Anlamak için JavaScript’te Yüksek Sıralı İşlevlere 5 Örnek – JSManifest

Daha İyi Anlamak için JavaScript'te Yüksek Sıralı İşlevlere 5 Örnek – JSManifest

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, .forEachvb.

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' }}>
        &nbsp;&nbsp;
        <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' }}>
        &nbsp;&nbsp;
        <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)

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.