나는 로더쉬를 저장하고 가방의 크기를 줄이는 14가지 기능을 했다.
55253 단어 webdevshowdevjavascripttutorial
나는 최근에 우리의 메인 프로그램을 훑어보았는데, 패키지의 크기를 줄이기를 희망했고, 비록 우리가 특정 기능의 도입을 위해 최선을 다했지만, 우리는 여전히 대부분의lodash를 수입하고 있다는 것을 곧 발견했다.
우리는lodashes로 이사했는데, 이것은 약간의 도움이 되었지만, 나는 여전히 실용적인 기능을 찾고 있다. 그것들은 패키지의 30퍼센트 정도를 차지한다.
문제는 노드 모듈로서 라이브러리에서polyfilling의 낡은 기능에 대한 선택이 많이 이루어졌기 때문에 목표 브라우저에 따라 필요하지 않은 코드가 많을 수 있습니다.
나는lodash에서 사용한 14개의 핵심 함수를 확정하고 현대Javascript로 다시 작성하기 시작했다. 이렇게 묶는 과정은 목표에 따라 어떤 다중 충전이 필요한지 결정할 수 있다.수입 규모가 대폭 감소하다.
나무가 흔들리면 내 기능에 앞서
내 코드: 4.1kb (압축되지 않음/통일되지 않음, 비교적 오래된 브라우저에 다각형 채우기 필요)
핵심 기능
다음은 함수 목록에 대한 내 작업입니다.
일치 기능
"그만해".
기능
다음은 이 함수들입니다. 이 함수들은 무엇을 하는지, 그리고 제가 어떻게 실현하는지.
선택(기능(항목)=>값|속성 이름)
우리는 다른 모든 것에 매우 유용하기 때문에
pick
부터 시작할 것이다.pick
은 대상에서 속성을 추출하는 함수를 되돌려줍니다. 문자열을 이 문자열로 변환하지만 다른 값을 사용하지 않습니다.pick
:const array = [{ name: "mike", a: 1 }, { name: "bob", a: 2 }]
console.log(array.map(pick('name')) //=> ["mike", "bob"]
구현import {get} from './get'
export function pick(fn) {
return typeof fn === "string" ? (v) => get(v,fn) : fn
}
필터(배열, 함수(항목)=>부울 값|문자열)
우리는name 속성을 가진
filter
을 자주 사용하기 때문에 Filter는 기본적으로pick이고 기존의 Filter 함수는 다음과 같다.const array = [{ name: "mike", a: 1 }, { name: "bob", a: 2 }, { a: 4 }]
console.log(filter(array, 'name')) //=> [{ name: "mike", a: 1 }, { name: "bob", a: 2 }]
구현import { pick } from "./pick"
export function filter(target, fn) {
return target.filter(pick(fn))
}
forEach(배열 | 객체, 함수(값, 키)
lodash에서 forEach에 대상이나 그룹을 사용할 수 있기 때문에 이를 실현하기 위한 실현이 필요합니다.리셋 함수 획득 매개 변수
value
과 key
.작동 방식은 다음과 같습니다.const data = { a: 1, b: 2, d: "hello" }
forEach(data, (value, key)=>console.log(`${key}=${value}`)
//=> a=1
//=> b=2
//=> d=hello
구현import { pick } from "./pick"
export function applyArrayFn(target, fnName, fn) {
fn = pick(fn)
if (Array.isArray(target)) return target[fnName](fn)
if (target && typeof target === "object")
return Object.entries(target)[fnName](([key, value], index) =>
fn(value, key, target, index)
)
throw new Error(`Cannot iterate ${typeof target}`)
}
export function forEach(target, fn) {
return applyArrayFn(target, "forEach", fn)
}
가져오기(객체, 속성 경로, 기본값)
get
에서는 객체에서 속성을 읽을 수 있으며 브로커나 최종 값을 찾지 못하면 기본값을 반환합니다.const data = { a: { b: {d: 1 } } }
get(data, "a.b.d") //=> 1
get(data, "a.c.d", "hmmm") //=> hmmm
구현export function get(object, path, defaultValue) {
const parts = path.split(".")
for (let part of parts) {
if(!object) return defaultValue
object = object[part]
}
return object ?? defaultValue
}
그룹 By (배열, 함수 (항목) = > 키 | propertyName)
함수(또는 선택된 속성 이름)의 결과로 키프레임을 설정하는 객체를 만듭니다. 여기서 각 값은 같은 키프레임을 가진 항목의 배열입니다.
const array = [{ name: "mike", type: "user" }, { name: "bob", type: "user" }, { name: "beth", type: "admin"} ]
console.log(groupBy(array, 'type'))
/*=>
{
admin: [{name: "beth", type: "admin" }],
user: [{name: "mike", type: "user" }, {name: "bob", type: "user"}]
}
*/
구현import { pick } from "./pick"
export function groupBy(target, fn) {
fn = pick(fn)
return target
.map((value) => ({ value, key: fn(value) }))
.reduce((c, a) => {
c[a.key] = c[a.key] || []
c[a.key].push(a.value)
return c
}, {})
}
keyBy (배열, 함수 (항목) = > key | propertyName)
groupBy
과 유사하지만, 결과는 마지막 키와 일치하는 항목입니다. 보통 이것은 주어진 것이고, 그 중 키는 유일한 (예: id) 이며, 검색을 만들 것입니다.const array = [{ id: "a7", name: "mike", type: "user" }, { id: "z1", name: "bob", type: "user" }, { id: "a3", name: "beth", type: "admin"} ]
console.log(keyBy(array, 'id'))
/*=>
{
"a3": {name: "beth", type: "admin", id: "a3" },
"a7": {name: "mike", type: "user", id: "a7" },
"z1": {name: "bob", type: "user", id: "z1"}
}
*/
구현import { pick } from "./pick"
export function keyBy(target, fn) {
fn = pick(fn)
return target
.map((value) => ({ value, key: fn(value) }))
.reduce((c, a) => {
c[a.key] = a.value
return c
}, {})
}
매핑(배열 | 객체, 함수(값, 키) = >value | 속성 이름)
매핑 객체 및 배열(예:
forEach
)const records = {
"a3": {name: "beth", type: "admin" },
"a7": {name: "mike", type: "user" },
"z1": {name: "bob", type: "user"}
}
console.log(map(records, 'name')) /=> ["beth", "mike", "bob"]
구현import { pick } from "./pick"
export function applyArrayFn(target, fnName, fn) {
fn = pick(fn)
if (Array.isArray(target)) return target[fnName](fn)
if (target && typeof target === "object")
return Object.entries(target)[fnName](([key, value], index) =>
fn(value, key, target, index)
)
throw new Error(`Cannot iterate ${typeof target}`)
}
export function forEach(target, fn) {
return applyArrayFn(target, "map", fn)
}
병합(대상,...소스)
그 작업 원리는
Object.assign
과 유사하지만, 끝까지 깊이 들어가 그것들을 교체하는 것이 아니라 더욱 깊은 대상을 갱신할 것이다.const record = { id: "2", name: "Beth", value: 3, ar: ["test", { a: 3, d: { e: 4 } }] }
console.log(merge(record, { ar: [{ b: 1 }, { c: 3, d: { f: 5 } }]))
/*=>
{
id: "2",
name: "Beth",
value: 3,
ar: [{ b: 1 }, { c: 3, d: { f: 5, e: 4 } }]
}
*/
구현export function merge(target, ...sources) {
for (let source of sources) {
mergeValue(target, source)
}
return target
function innerMerge(target, source) {
for (let [key, value] of Object.entries(source)) {
target[key] = mergeValue(target[key], value)
}
}
function mergeValue(targetValue, value) {
if (Array.isArray(value)) {
if (!Array.isArray(targetValue)) {
return [...value]
} else {
for (let i = 0, l = value.length; i < l; i++) {
targetValue[i] = mergeValue(targetValue[i], value[i])
}
return targetValue
}
} else if (typeof value === "object") {
if (targetValue && typeof targetValue === "object") {
innerMerge(targetValue, value)
return targetValue
} else {
return value ? { ...value } : value
}
} else {
return value ?? targetValue ?? undefined
}
}
}
생략(객체, arrayOffrops)
제거한 아이템의 대상을 되돌려줍니다
const record = { a: 1, b: 2, c: 3}
console.log(omit(record, ['b', 'c'])) //=> {a: 1}
구현export function omit(target, props) {
return Object.fromEntries(
Object.entries(target).filter(([key]) => !props.includes(key))
)
}
컬렉션(객체, 속성 경로, 값)
대상의 값을 설정하고 필요하면 빈 대상
{}
을 만듭니다.const record = { a: 1, d: { e: 1 } }
set(record, "a.d.e", 2) //=> { a: 1, d: { e: 2 } }
set(record, "a.b.c", 4) //=> { a: 1, b: { c: 4 }, d: { e: 2 } }
구현export function set(object, path, value) {
const parts = path.split(".")
for (let i = 0, l = parts.length - 1; i < l; i++) {
const part = parts[i]
object = object[part] = object[part] || {}
}
object[parts[parts.length - 1]] = value
}
정렬 방식(배열, 함수(항목)=>value | 속성 이름)
배열을 하위 요소별로 정렬합니다.
const array = [{ id: "a7", name: "mike", type: "user" }, { id: "z1", name: "bob", type: "user" }, { id: "a3", name: "beth", type: "admin"} ]
console.log(sortBy(array, 'name'))
/*=>
[
{ id: "a3", name: "beth", type: "admin"}
{ id: "z1", name: "bob", type: "user" },
{ id: "a7", name: "mike", type: "user" },
]
*/
구현import { pick } from "./pick"
export function sortBy(array, fn) {
fn = pick(fn)
return array.sort((a, b) => {
const va = fn(a)
const vb = fn(b)
if (va < vb) return -1
if (va > vb) return 1
return 0
})
}
어레이
기존 스토리지에서 고유한 스토리지 생성
const array = ['a', 'b', 'c', 'b', 'b', 'a']
console.log(uniq(array)) //=> ['a', 'b', 'c']
구현export function uniq(target) {
return Array.from(new Set(target))
}
uniqBy(배열, 함수(항목)=>value | 속성 이름)
그룹의 대상의 속성을 사용하여 uniq 그룹을 만듭니다.
const array = [{a: 1, b: 2}, {a: 4, b: 2}, {a: 5, b: 3}]
console.log(uniqBy(array, 'b')) //=> [{a: 1, b: 2}, {a: 5, b: 3}]
구현import { pick } from "./pick"
export function uniqBy(target, fn) {
fn = pick(fn)
const dedupe = new Set()
return target.filter((v) => {
const k = fn(v)
if (dedupe.has(k)) return false
dedupe.add(k)
return true
})
}
부분적으로 이루어진 탈온스
lodash
debounce
은 아주 강해요. 저한테는 너무 강해요. 너무 커요.나는 온스에 가서 가장 긴 대기 시간을 보내고, 마운트된 호출을 새로 고치거나 취소할 수 있는 기능이 필요하다.(그래서 부족한 것은 후연과 전연 등, 그리고 내가 사용하지 않는 다른 옵션이다.)const debounced = debounce(()=>save(), 1000, {maxWait: 10000})
...
debounced() // Call the debounced function after 1s (max 10s)
debounced.flush() // call any pending
debounced.cancel() // cancel any pending calls
구현export function debounce(fn, wait = 0, { maxWait = Infinity } = {}) {
let timer = 0
let startTime = 0
let running = false
let pendingParams
let result = function (...params) {
pendingParams = params
if (running && Date.now() - startTime > maxWait) {
execute()
} else {
if (!running) {
startTime = Date.now()
}
running = true
}
clearTimeout(timer)
timer = setTimeout(execute, Math.min(maxWait - startTime, wait))
function execute() {
running = false
fn(...params)
}
}
result.flush = function () {
if (running) {
running = false
clearTimeout(timer)
fn(...pendingParams)
}
}
result.cancel = function () {
running = false
clearTimeout(timer)
}
return result
}
결론
만약 당신이 이 기능들만 사용한다면,lodash가 더 이상 필요하지 않을 수도 있습니다.우리 프로그램에서, 우리는 확실히 다른lodash 함수를 사용했지만, 모두 타성 가져오기 (예:
template
) 를 지원하기 때문에, 우리 프로그램의 불러오는 속도가 훨씬 빠르다.프로젝트에서 이 코드를 마음대로 사용할 수 있습니다.
Reference
이 문제에 관하여(나는 로더쉬를 저장하고 가방의 크기를 줄이는 14가지 기능을 했다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/miketalbot/14-functions-so-you-can-dump-lodash-and-reduce-your-bundle-size-3gg9텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)