owned this note
owned this note
Published
Linked with GitHub
# lodash
https://lodash.com/
lodash 是 js 處理 arrays, numbers, objects, strings專用的函式庫
## You don't need lodash
在使用前先理解自己開發上需要什麼工具
或許某些東西你不需要這些套件
[You don't need](https://github.com/you-dont-need)
[You don't need lodash](https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore)
lodash所有的功能都可以透過Js實踐出來
同理如果不想引用外部套件可以可以自己在專案內實踐這些方法
我們可以看看這些大前輩們是怎麼封裝這些方法的
## 相容性
可針對許多舊瀏覽器不支援es5操作
## 數學運算
```javascript=
// js
Math.round(1.7241 * 1000) / 1000
_.round(4.006);
// => 4
_.round(4.006, 2);
// => 4.01
_.round(4060, -2);
// => 4100
```
```javascript
// Closure
(function() {
/**
* Decimal adjustment of a number.
*
* @param {String} type The type of adjustment.
* @param {Number} value The number.
* @param {Integer} exp The exponent (the 10 logarithm of the adjustment base).
* @returns {Number} The adjusted value.
*/
function decimalAdjust(type, value, exp) {
// If the exp is undefined or zero...
if (typeof exp === 'undefined' || +exp === 0) {
return Math[type](value);
}
value = +value;
exp = +exp;
// If the value is not a number or the exp is not an integer...
if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
return NaN;
}
// Shift
value = value.toString().split('e');
value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));
// Shift back
value = value.toString().split('e');
return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));
}
// Decimal round
if (!Math.round10) {
Math.round10 = function(value, exp) {
return decimalAdjust('round', value, exp);
};
}
// Decimal floor
if (!Math.floor10) {
Math.floor10 = function(value, exp) {
return decimalAdjust('floor', value, exp);
};
}
// Decimal ceil
if (!Math.ceil10) {
Math.ceil10 = function(value, exp) {
return decimalAdjust('ceil', value, exp);
};
}
})();
// Round
Math.round10(55.55, -1); // 55.6
Math.round10(55.549, -1); // 55.5
Math.round10(55, 1); // 60
Math.round10(54.9, 1); // 50
Math.round10(-55.55, -1); // -55.5
Math.round10(-55.551, -1); // -55.6
Math.round10(-55, 1); // -50
Math.round10(-55.1, 1); // -60
// Floor
Math.floor10(55.59, -1); // 55.5
Math.floor10(59, 1); // 50
Math.floor10(-55.51, -1); // -55.6
Math.floor10(-51, 1); // -60
// Ceil
Math.ceil10(55.51, -1); // 55.6
Math.ceil10(51, 1); // 60
Math.ceil10(-55.59, -1); // -55.5
Math.ceil10(-59, 1); // -50
// lodash
_.ceil(4.006);
// => 5
_.ceil(6.004, 2);
// => 6.01
_.ceil(6040, -2);
// => 6100
```
## filter
### 資料
```javascript
const list = [
{
name: '王小明',
age: 20,
items : [ '鞋子', '襪子' ]
},
{
name: '張小美',
age: 23,
items : [ '鞋子', '襪子', '裙子']
},
{
name: '劉彥伶',
age: 26,
items : [ '褲子', '眼鏡' ]
},
{
name: '王小明',
age: 23,
items : [ '鞋子' ]
},
];
```
### 更好的程式碼可讀性
```javascript
const filterByObj = list.filter(item => item.name === '王小明')
const _filterByObj = _.filter(list, {name: '王小明'});
// - log 兩位王小明
const filterByObj2 = list.filter(item => item.age > 21)
const _filterByObj2 = _.filter(list, (o) => o.age > 21);
//. 三位>21歲
const _filterByObj3= _.filter(list, {
age: 23,
items : [ '鞋子' ]
});
// - index 1,3
```
## sort
### 資料
```javascript
const list = [
{
name: '張小美',
age: 22,
},
{
name: 'Iven',
age: 28,
},
{
name: '劉彥伶',
age: 21,
},
{
name: '王小明',
age: 26,
},
{
name: 'Iven',
age: 21,
},
];
```
### 更好閱讀的程式碼
```javascript
// 升序排列
const _sort = _.orderBy(list, ['age'], ['asc'])
const sort = list.sort((a, b)=> {
return a.age - b.age;
});
// 以user升序再以age降序
const _sort2 = _.orderBy(list, ['name', 'age'], ['asc', 'desc']);
const sort2 = list.sort(function(a, b) {
if (a.name < b.name) {
return -1;
} else if (a.name > b.name) {
return 1;
} else {
return b.age - a.age;
}
});
console.log(_sort2)
console.log(sort2)
```
## debounce
```javascript
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function() {
timeout = null;
if (!immediate) func.apply(context, args);
}, wait);
if (immediate && !timeout) func.apply(context, args);
};
}
```
## throttle
```javascript=
function throttle(func, timeFrame) {
var lastTime = 0;
return function (...args) {
var now = new Date();
if (now - lastTime >= timeFrame) {
func(...args);
lastTime = now;
}
};
}
```
## isEmpty
```javascript=
// Lodash
console.log(_.isEmpty(null))
// output: true
console.log(_.isEmpty(''))
// output: true
console.log(_.isEmpty({}))
// output: true
console.log(_.isEmpty([]))
// output: true
console.log(_.isEmpty({a: '1'}))
// output: false
// Native
const isEmpty = obj => [Object, Array].includes((obj || {}).constructor) && !Object.entries((obj || {})).length;
console.log(isEmpty(null))
// output: true
console.log(isEmpty(''))
// output: true
console.log(isEmpty({}))
// output: true
console.log(isEmpty([]))
// output: true
console.log(isEmpty({a: '1'}))
// output: false
```
## Sum
```javascript=
// 原生
const array1 = [1, 2, 3, 4];
// 0 + 1 + 2 + 3 + 4
const initialValue = 0;
const sumWithInitial = array1.reduce(
(accumulator, currentValue) => accumulator + currentValue,
initialValue
);
console.log(sumWithInitial);
// lodash
_sum(array1)
// Expected output: 10
```
## cloneDeep
講到cloneDeep 不得不先提的深拷貝
[參考資料](https://blog.errorbaker.tw/posts/clay/copy/)
[參考資料](https://zhuanlan.zhihu.com/p/67374716)
### 解構賦值
```javascript=
const obj = {
old: {
name: 'Clay',
age: 30
},
young: {
name: 'Xen',
age: 18
}
}
const copyObj = { ...obj }
console.log(obj === copyObj)
copyObj.young = 123456
console.log(obj)
console.log(obj === copyObj)
console.log(obj.young === copyObj.young)
console.log(obj.young.age === copyObj.young.age)
```
### Object.assign()
應付一層的深拷貝是可行的
### JSON.parse()和JSON.stringify()
大多數可能會快速想到的深拷貝辦法
#### JSON.parse()
json to a object or value
#### JSON.stringify()
javascript value to a json
```javascript
console.log(JSON.stringify({ x: 5, y: 6 }));
// Expected output: "{"x":5,"y":6}"
console.log(JSON.stringify([new Number(3), new String('false'), new Boolean(false)]));
// Expected output: "[3,"false",false]"
console.log(JSON.stringify({ x: [10, undefined, function(){}, Symbol('')] }));
// Expected output: "{"x":[10,null,null,null]}"
console.log(JSON.stringify(new Date(2006, 0, 2, 15, 4, 5)));
// Expected output: ""2006-01-02T15:04:05.000Z""
```
## _.get
```javascript=
// Lodash
var object = { a: [{ b: { c: 3 } }] };
var result = _.get(object, 'a[0].b.c', 1);
console.log(result);
// output: 3
// Native (ES6 - IE not supported)
var object = { a: [{ b: { c: 3 } }] };
var { a: [{ b: { c: result = 1 } = {} } = {}] = [] } = object;
console.log(result);
// output: 3
// Native (ES11)
var object = { a: [{ b: { c: 3 } }] };
var result = object?.a?.[0]?.b?.c ?? 1;
console.log(result);
// output: 3
// Native
const get = (obj, path, defaultValue = undefined) => {
const travel = regexp =>
String.prototype.split
.call(path, regexp)
.filter(Boolean)
.reduce((res, key) => (res !== null && res !== undefined ? res[key] : res), obj);
const result = travel(/[,[\]]+?/) || travel(/[,[\].]+?/);
return result === undefined || result === obj ? defaultValue : result;
};
var object = { a: [{ b: { c: 3 } }] };
var result = get(object, 'a[0].b.c', 1);
// output: 3
```