乐闻世界logo
搜索文章和话题

Lodash和原生JavaScript有什么区别?在什么情况下应该使用Lodash?

2月18日 21:40

在现代JavaScript开发中,Lodash和原生JavaScript都提供了许多相似的功能。以下是关于Lodash与原生JavaScript对比的详细解答:

Lodash vs 原生JavaScript对比

1. 数组操作

map、filter、reduce

原生JavaScript:

javascript
const numbers = [1, 2, 3, 4, 5]; // map const doubled = numbers.map(n => n * 2); // => [2, 4, 6, 8, 10] // filter const evens = numbers.filter(n => n % 2 === 0); // => [2, 4] // reduce const sum = numbers.reduce((acc, n) => acc + n, 0); // => 15

Lodash:

javascript
import _ from 'lodash'; const numbers = [1, 2, 3, 4, 5]; // map const doubled = _.map(numbers, n => n * 2); // => [2, 4, 6, 8, 10] // filter const evens = _.filter(numbers, n => n % 2 === 0); // => [2, 4] // reduce const sum = _.reduce(numbers, (acc, n) => acc + n, 0); // => 15

对比: 在这些基本操作上,原生JavaScript和Lodash功能基本相同,性能也相近。

数组去重

原生JavaScript:

javascript
// ES6 Set const unique = [...new Set([1, 2, 2, 3, 4, 4, 5])]; // => [1, 2, 3, 4, 5] // filter + indexOf const unique = [1, 2, 2, 3, 4, 4, 5].filter((item, index, arr) => arr.indexOf(item) === index );

Lodash:

javascript
const unique = _.uniq([1, 2, 2, 3, 4, 4, 5]); // => [1, 2, 3, 4, 5] // 按某个属性去重对象数组 const users = [ { id: 1, name: 'John' }, { id: 2, name: 'Jane' }, { id: 1, name: 'John' } ]; const uniqueUsers = _.uniqBy(users, 'id');

对比: Lodash的_.uniqBy()在处理对象数组时更方便。

数组分组

原生JavaScript:

javascript
const people = [ { name: 'Alice', age: 25 }, { name: 'Bob', age: 25 }, { name: 'Charlie', age: 30 } ]; const grouped = people.reduce((acc, person) => { const key = person.age; if (!acc[key]) acc[key] = []; acc[key].push(person); return acc; }, {});

Lodash:

javascript
const grouped = _.groupBy(people, 'age'); // => { '25': [{...}, {...}], '30': [{...}] }

对比: Lodash的_.groupBy()更简洁易读。

2. 对象操作

深拷贝

原生JavaScript:

javascript
// JSON方法(有局限性) const copy = JSON.parse(JSON.stringify(original)); // 结构化克隆(现代浏览器) const copy = structuredClone(original); // 手动实现 function deepClone(obj) { if (obj === null || typeof obj !== 'object') return obj; if (obj instanceof Date) return new Date(obj); if (obj instanceof Array) return obj.map(item => deepClone(item)); const clonedObj = {}; for (let key in obj) { if (obj.hasOwnProperty(key)) { clonedObj[key] = deepClone(obj[key]); } } return clonedObj; }

Lodash:

javascript
const copy = _.cloneDeep(original);

对比: Lodash的_.cloneDeep()更简单、更可靠,支持更多数据类型。

安全获取嵌套属性

原生JavaScript:

javascript
const user = { profile: { name: 'John' } }; // 可选链操作符(ES2020) const name = user?.profile?.name; const defaultName = user?.profile?.name ?? 'default'; // 传统方式(容易出错) const name = user && user.profile && user.profile.name;

Lodash:

javascript
const name = _.get(user, 'profile.name'); const defaultName = _.get(user, 'profile.name', 'default');

对比: Lodash的_.get()在旧浏览器中更兼容,且提供默认值支持更优雅。

对象合并

原生JavaScript:

javascript
// 浅拷贝合并 const merged = { ...obj1, ...obj2 }; // Object.assign const merged = Object.assign({}, obj1, obj2); // 深度合并(需要手动实现) function deepMerge(target, source) { const output = { ...target }; if (isObject(target) && isObject(source)) { Object.keys(source).forEach(key => { if (isObject(source[key])) { if (!(key in target)) { Object.assign(output, { [key]: source[key] }); } else { output[key] = deepMerge(target[key], source[key]); } } else { Object.assign(output, { [key]: source[key] }); } }); } return output; }

Lodash:

javascript
const merged = _.merge({}, obj1, obj2);

对比: Lodash的_.merge()提供深度合并,更简单可靠。

3. 性能对比

测试场景:数组操作

javascript
// 测试数据 const largeArray = Array.from({ length: 100000 }, (_, i) => i); // map性能测试 console.time('native map'); largeArray.map(n => n * 2); console.timeEnd('native map'); console.time('lodash map'); _.map(largeArray, n => n * 2); console.timeEnd('lodash map');

结果: 在大多数情况下,原生JavaScript的性能略优于Lodash,但差异不大。

测试场景:深拷贝

javascript
const largeObject = { a: 1, b: { c: 2, d: { e: 3 } } }; console.time('native JSON'); JSON.parse(JSON.stringify(largeObject)); console.timeEnd('native JSON'); console.time('lodash cloneDeep'); _.cloneDeep(largeObject); console.timeEnd('lodash cloneDeep');

结果: Lodash的_.cloneDeep()通常比JSON.parse(JSON.stringify())更快,且支持更多数据类型。

4. 浏览器兼容性

功能原生JavaScriptLodash
Array.prototype.mapES5 (IE9+)所有浏览器
Array.prototype.filterES5 (IE9+)所有浏览器
Array.prototype.reduceES5 (IE9+)所有浏览器
可选链操作符ES2020 (不支持IE)所有浏览器
空值合并操作符ES2020 (不支持IE)所有浏览器
结构化克隆现代浏览器所有浏览器

5. 代码可读性

原生JavaScript:

javascript
const result = users .filter(user => user.age > 18) .map(user => ({ id: user.id, name: user.name.toUpperCase() })) .sort((a, b) => a.name.localeCompare(b.name));

Lodash:

javascript
const result = _.chain(users) .filter(user => user.age > 18) .map(user => ({ id: user.id, name: _.toUpper(user.name) })) .orderBy('name') .value();

对比: Lodash的链式调用在某些场景下更易读,但原生JavaScript的链式调用也很清晰。

6. 打包体积

原生JavaScript: 无额外体积

Lodash:

  • 完整引入:约70KB (gzipped)
  • 按需引入:每个方法约1-2KB
  • 使用lodash-es:支持Tree-shaking
javascript
// 完整引入(不推荐) import _ from 'lodash'; // 按需引入(推荐) import cloneDeep from 'lodash/cloneDeep'; import debounce from 'lodash/debounce';

7. 何时使用Lodash?

推荐使用Lodash的场景:

  1. 需要支持旧版浏览器
  2. 需要深度拷贝、深度合并等复杂操作
  3. 需要链式调用处理复杂数据转换
  4. 团队已经熟悉Lodash API
  5. 需要防抖、节流等工具函数

推荐使用原生JavaScript的场景:

  1. 只需要基本的数组、对象操作
  2. 追求最小的打包体积
  3. 目标浏览器支持现代JavaScript特性
  4. 项目对性能要求极高

8. 最佳实践

javascript
// 混合使用示例 import { debounce, throttle } from 'lodash'; class SearchComponent { constructor() { this.debouncedSearch = debounce(this.performSearch.bind(this), 300); } handleInput(event) { const value = event.target.value; // 使用原生方法处理简单操作 const trimmed = value.trim(); const normalized = trimmed.toLowerCase(); // 使用Lodash处理复杂操作 if (normalized) { this.debouncedSearch(normalized); } } performSearch(keyword) { // 使用原生方法 const results = this.data.filter(item => item.name.toLowerCase().includes(keyword) ); // 使用Lodash方法 const sortedResults = _.orderBy(results, ['score'], ['desc']); this.displayResults(sortedResults); } }

总结

Lodash和原生JavaScript各有优势:

  • 原生JavaScript:性能更好、体积更小、API更现代
  • Lodash:兼容性更好、API更丰富、某些操作更简洁

在实际项目中,建议:

  1. 优先使用原生JavaScript的ES6+特性
  2. 在需要复杂操作或兼容旧浏览器时使用Lodash
  3. 按需引入Lodash方法,避免引入整个库
  4. 根据团队习惯和项目需求做出选择
标签:Lodash