آموزش جامع Lodash
کتابخانه ابزار کاربردی جاوااسکریپت — بیش از ۳۰۰ تابع آماده برای کار با داده.
📚معرفی و نصب
Lodash یک کتابخانه Utility برای جاوااسکریپت است که بیش از ۳۰۰ تابع آماده برای کار با آرایه، شیء، رشته و تابع فراهم میکند. عملیاتی که با JS خالص ۱۰ خط نیاز دارد، با Lodash ۱ خط است.
🔒
ایمنی null
بدون خطای undefined
⚡
عملکرد بالا
lazy evaluation
📋
Immutable
داده اصلی دست نخورد
🔌
+300 تابع
برای هر نیازی
نصب
<!-- فایل لوکال --> <script src="lodash.min.js"></script> // استفاده با _ (underscore) _.chunk([1,2,3,4], 2); // → [[1,2],[3,4]] _.sum([1,2,3]); // → 6 // NPM / ES Module import _ from 'lodash' // یا فقط تابع موردنیاز (tree-shaking) import chunk from 'lodash/chunk'
ⓘ نکته: Lodash از طریق متغیر سراسری
_ در دسترس است. در پروژههای بزرگ برای کاهش bundle size، فقط توابع موردنیاز را import کنید.
📈توابع آرایه (Array)
| تابع | توضیح | مثال |
|---|---|---|
| _.chunk(arr, n) | تقسیم به قطعات nتایی | [1,2,3,4] → [[1,2],[3,4]] |
| _.compact(arr) | حذف مقادیر falsy | [0,'',false,1] → [1] |
| _.uniq(arr) | حذف تکراریها | [1,2,1,3] → [1,2,3] |
| _.uniqBy(arr, key) | حذف تکراری بر اساس کلید | uniqBy(users,'id') |
| _.flatten(arr) | flat یک سطح | [[1,2],[3]] → [1,2,3] |
| _.flattenDeep(arr) | flat کامل عمیق | [1,[2,[3]]] → [1,2,3] |
| _.difference(a, b) | اختلاف دو آرایه | [1,2,3],[2] → [1,3] |
| _.intersection(a, b) | اشتراک دو آرایه | [1,2],[2,3] → [2] |
| _.union(a, b) | اجتماع بدون تکرار | [1,2],[2,3] → [1,2,3] |
| _.shuffle(arr) | درهمریختن تصادفی | _.shuffle([1,2,3,4,5]) |
| _.sample(arr) | یک عنصر تصادفی | _.sample([1,2,3]) → 2 |
| _.sampleSize(arr, n) | n عنصر تصادفی | _.sampleSize([1..5], 3) |
| _.take(arr, n) | n عنصر اول | _.take([1,2,3,4], 2) → [1,2] |
| _.drop(arr, n) | حذف n عنصر اول | _.drop([1,2,3,4], 2) → [3,4] |
| _.zip / _.unzip | ترکیب/جدا کردن آرایهها | _.zip([1,2],['a','b']) → [[1,'a'],[2,'b']] |
▶ آزمایشگاه: توابع آرایه
نتیجه اینجا نشان داده میشود...
📋توابع Collection
این توابع روی هر دو آرایه و شیء کار میکنند — ایدهآل برای پردازش داده.
| تابع | توضیح |
|---|---|
| _.groupBy(col, key) | گروهبندی بر اساس کلید یا تابع |
| _.sortBy(col, key) | مرتبسازی صعودی |
| _.orderBy(col, keys, dirs) | مرتبسازی با جهت asc/desc |
| _.countBy(col, fn) | شمارش بر اساس معیار |
| _.filter(col, predicate) | فیلتر با شرط / شیء |
| _.find(col, predicate) | اولین مورد منطبق |
| _.map(col, fn) | تبدیل هر آیتم |
| _.reduce(col, fn, init) | تجمیع |
| _.every / _.some | همه / حداقل یکی شرط را دارند |
| _.keyBy(col, key) | تبدیل آرایه به شیء با کلید |
| _.flatMap(col, fn) | map + flatten |
const students = [ { name: 'علی', grade: 'A', score: 95, city: 'تهران' }, { name: 'سارا', grade: 'B', score: 82, city: 'اصفهان' }, { name: 'رضا', grade: 'A', score: 88, city: 'تهران' }, { name: 'مینا', grade: 'B', score: 75, city: 'مشهد' }, { name: 'حسین', grade: 'A', score: 72, city: 'اصفهان' }, { name: 'فاطمه', grade: 'B', score: 91, city: 'تهران' }, ]; _.groupBy(students, 'grade'); // → { A: [{علی},{رضا},{حسین}], B: [{سارا},{مینا},{فاطمه}] } _.orderBy(students, ['score'], ['desc']); // → [{علی,95},{فاطمه,91},{رضا,88},...] _.keyBy(students, 'name'); // → { 'علی': {name:'علی',...}, 'سارا': {...} }
▶ آزمایشگاه: Collection با داده دانشجویان
نتیجه اینجا نشان داده میشود...
💾توابع Object (شیء)
const obj = { a: 1, b: { c: 2, d: 3 }, e: [4,5] }; // کپی عمیق — بدون اشاره به اصل const copy = _.cloneDeep(obj); // دسترسی ایمن به nested — بدون خطای TypeError _.get(obj, 'b.c'); // → 2 _.get(obj, 'x.y.z', 'default'); // → 'default' (نه خطا!) // تنظیم مقدار nested _.set(obj, 'b.e', 99); // ادغام عمیق _.merge({ a:1, b:{ x:1 } }, { b:{ y:2 }, c:3 }); // → { a:1, b:{x:1,y:2}, c:3 } // انتخاب / حذف کلیدها _.pick(obj, ['a', 'e']); // → { a:1, e:[4,5] } _.omit(obj, ['a']); // → { b:{c:2,d:3}, e:[4,5] } // مقایسه عمیق _.isEqual({ a:1 }, { a:1 }); // → true (برخلاف ===) // کلیدها / مقادیر / جفتها _.keys(obj); // → ['a','b','e'] _.values(obj); // → [1,{c:2,d:3},[4,5]] _.toPairs(obj); // → [['a',1],['b',{...}],...] // مقدار پیشفرض — فقط اگر undefined باشد _.defaults({ a:1 }, { a:99, b:2 }); // → { a:1, b:2 }
▶ آزمایشگاه: توابع Object
نتیجه اینجا نشان داده میشود...
🔡توابع String (رشته)
| تابع | توضیح | خروجی نمونه |
|---|---|---|
| _.camelCase(str) | به camelCase | fooBarBaz |
| _.kebabCase(str) | به kebab-case | foo-bar-baz |
| _.snakeCase(str) | به snake_case | foo_bar_baz |
| _.startCase(str) | هر کلمه بزرگ | Foo Bar Baz |
| _.capitalize(str) | اول بزرگ، بقیه کوچک | Hello world |
| _.truncate(str,opts) | برش با ... | Hello Wor... |
| _.pad(str,len,char) | پد از دو طرف | --hi-- |
| _.padStart/End | پد از ابتدا/انتها | 00042 |
| _.repeat(str,n) | تکرار رشته | ha ha ha |
| _.escape(str) | escape HTML | <script> |
| _.words(str) | جدا کردن کلمات | ['foo','bar'] |
▶ آزمایشگاه: توابع String
نتیجه اینجا نشان داده میشود...
⏰debounce و throttle
ⓘ تفاوت:
debounce — تابع را فقط پس از اینکه برای مدت X دیگر فراخوانی نشود اجرا میکند (مثل جستجو: بعد از اتمام تایپ).
throttle — تابع را حداکثر هر X میلیثانیه یکبار اجرا میکند (مثل scroll: حداکثر ۵ بار در ثانیه).
// debounce — جستجو: فقط بعد از 500ms سکوت const search = _.debounce((query) => { fetchAPI(query); // درخواست به سرور }, 500); input.addEventListener('input', e => search(e.target.value)); // throttle — scroll: حداکثر هر 200ms const onScroll = _.throttle(() => { console.log('scroll:', window.scrollY); }, 200); window.addEventListener('scroll', onScroll); // لغو search.cancel(); // لغو debounce در حال انتظار search.flush(); // اجرای فوری بدون انتظار // once — فقط یک بار اجرا const init = _.once(() => { console.log('فقط یک بار!'); });
▶ آزمایشگاه زنده: در کادر تایپ کنید
بدون کنترل (هر keystroke)
0
بار فراخوانی شد
debounce (600ms بعد از توقف)
0
بار اجرا شد
throttle (حداکثر هر 500ms)
0
بار اجرا شد
🔢Math و Utility
// ─── Math ─── _.random(1, 100); // عدد تصادفی صحیح بین ۱-۱۰۰ _.random(1.0, 5.0); // عدد تصادفی اعشاری _.clamp(120, 0, 100); // → 100 (محدود بین min/max) _.clamp(-5, 0, 100); // → 0 _.inRange(5, 1, 10); // → true _.sum([1,2,3]); // → 6 _.mean([1,2,3]); // → 2 // ─── Type Checking ─── _.isArray([1,2]); // → true _.isObject({}); // → true _.isString('hi'); // → true _.isNumber(42); // → true _.isFunction(() => {}); // → true _.isNil(null); // → true (null یا undefined) _.isEmpty([]); // → true _.isEmpty({}); // → true _.isEmpty(''); // → true // ─── Utility ─── _.times(5, i => i * 2); // → [0,2,4,6,8] _.range(1, 6); // → [1,2,3,4,5] _.range(0, 10, 2); // → [0,2,4,6,8] (با گام ۲) _.uniqueId('item_'); // → 'item_1', 'item_2', ... _.noop(); // تابع خالی _.identity(42); // → 42 (همان ورودی) _.memoize(expensiveFn); // کش کردن نتیجه تابع
▶ آزمایشگاه: Math و Utility
نتیجه اینجا نشان داده میشود...
🏆پروژه کامل — تحلیل داده
ترکیب چندین تابع Lodash برای تحلیل یک لیست سفارشات:
const orders = [ { id:1, user:'علی', city:'تهران', product:'لپتاپ', price:35000000, qty:1 }, { id:2, user:'سارا', city:'اصفهان', product:'موبایل', price:18000000, qty:2 }, { id:3, user:'رضا', city:'تهران', product:'تبلت', price:12000000, qty:3 }, { id:4, user:'مینا', city:'مشهد', product:'لپتاپ', price:42000000, qty:1 }, { id:5, user:'حسین', city:'اصفهان', product:'موبایل', price:22000000, qty:1 }, { id:6, user:'فاطمه', city:'تهران', product:'هدفون', price:4500000, qty:4 }, ]; // ۱. مجموع فروش هر شهر const byCity = _.groupBy(orders, 'city'); const cityRevenue = _.mapValues(byCity, items => _.sumBy(items, o => o.price * o.qty) ); // ۲. پرفروشترین محصول const topProduct = _.maxBy( _.map(_.groupBy(orders, 'product'), (items, name) => ({ name, total: _.sumBy(items, o => o.price * o.qty) })), 'total' ); // ۳. مرتبسازی سفارشات بر اساس ارزش کل (نزولی) const sorted = _.orderBy(orders, [o => o.price * o.qty], ['desc'] );
▶ دمو: تحلیل سفارشات زنده
یک دکمه را کلیک کنید...
💡 خلاصه Lodash در یک نگاه:
_.groupBy / _.orderBy / _.countBy— تجزیه و تحلیل داده_.get / _.set / _.cloneDeep— کار ایمن با object_.debounce / _.throttle— کنترل عملکرد_.chunk / _.uniq / _.shuffle— عملیات آرایه_.camelCase / _.truncate— پردازش رشته_.isNil / _.isEmpty / _.isEqual— بررسی نوع و مقدار
🚀زمین بازی کد (Playground)
کد Lodash را اجرا کن و خروجی را در پنل کنسول ببین. توابع آرایه، collection و object را امتحان کن. نسخهٔ ۴.۱۷.۲۱ آفلاین بارگذاری میشود.