WEB

언더스코어-정리

paulaner80 2017. 12. 29. 11:27
반응형

언더스코어란?

코딩을 도와주는 자바스크립트 라이브러리로 매우 작은 용량에 80여가지의 function을 제공. 언더스코어 함수중에는 ES5, ES6를 거쳐 내장함수로 이미 지원하는 함수들이 있으므로 이미 브라우저 내장함수로 지원하고있다면 성능을 위해 내장함수를 이용하자.

 

용어설명

Context

bind로 묶어준다.

iteratee

반복처리 시키는 내용이다.

 

 

Context와 iteratee의 구분

 // _.each(list, iteratee, [context])

 _.each([1, 2, 3], alert);

 

 => alerts each number in turn...

 

 _.each(, alert);

 

 => alerts each number value in turn... 

 


context를 지정하지 않았을 경우 list의 내용들이 iteratee를 통해 처리된다

 

_.each([1, 2, 3], function(num) {

 

  // In here, "this" refers to the same Array as "someOtherArray"

 

  alert( this[num] ); // num is the value from the array being iterated

                      //    so this[num] gets the item at the "num" index of

                      //    someOtherArray.

}, someOtherArray);

context가 있을 경우 this로 바인딩한다.

 

 

Collections Functions (Arrays or Objects)

 

each


각 요소에 iteratee를 적용한 결과를 리턴한다.

 

var arr = [{"one":"11111"},{"two":"2222"}];
_.each(arr, function(value, index){
console.log("value : "+JSON.stringify(value) +", index:"+index);
})
//출력
//value : {"one":"11111"}, index:0
//value : {"two":"2222"}, index:1

 

 

map

each와 비슷하지만 새로운 콜렉션을 만듬

특화 함수 : pluck

//_.map(list, iteratee, [context])

_.map([1, 2, 3], function(num){ return num * 3; });

=> [3, 6, 9]

_.map(, function(num, key){ return num * 3; });

=> [3, 6, 9]

_.map([[1, 2], [3, 4]], _.first);

=> [1, 3] 

 

index가 필요한 경우

const arr = ["a", "b", "c", "d", "e", "f", "g"];

const res = _.map(arr, function(value, index) {
  return index + "=" + value;
});

console.log(res); //[ '0=a', '1=b', '2=c', '3=d', '4=e', '5=f', '6=g' ]
 

reduce

입력받은 리스트로부터 하나의 결과를 작성함 
memo는 reduction의 초기값 각각의 단계는 반드시 리턴값을 가져야하고 
해당 리턴값이 재귀함수형식으로 계속 반복실행되어야 한다.

 

reduce 함수에서 iteratee 함수 사용시에 list가 배열이냐, 객체이냐에 따라 사용하는 인자가 다르다.
list가 배열일 경우, iteratee 함수의 인자(arguments)로 (memo, element, index, list)를 사용한다.
list가 객체일 경우, iteratee 함수의 인자(arguments)로 (memo, value, key, list)를 사용한다.

 

사용가능한경우 ES5 reduce를 사용

//_.reduce(list, iteratee, [memo], [context])

var sum = _.reduce([1, 2, 3],function(memo, num){

  return memo + num;

}, 0);

 

=> 6

 

reduce를 사용해 promise를 순차적으로 실행할 수 있다.


 
  const bb = await _.reduce(
    subtractArr,
    async function(preProm, item) {
      const aa = await preProm;
      console.log("aa : " + JSON.stringify(aa));
      const { rows } = await asyncFunction1({code: item.name });
      if (rows.length > 0{
        const sud = rows[0].fvd;
        await asyncFuction2({code: item.birth });
        await asyncFuction3({code: item.tel });
        aa.push(sud);
        return Promise.resolve(aa);
      } else {
        return Promise.resolve();
      }
    },
    Promise.resolve([])
  );

  console.log("bb : " + JSON.stringify(bb));


reduceRight

reduce를 오른쪽부터 이어붙임(right-associative)

사용가능한경우 es5 reuce를 이용

//_.reduceRight(list, iteratee, memo, [context])

var list = [[0, 1], [2, 3], [4, 5]];

var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);

=> [4, 5, 2, 3, 0, 1] 

function a(cb){
console.log("this is fn a");
setTimeout(cb,1000);
}
function b(cb){
console.log("this is fn b");
setTimeout(cb,1000);
}
var fns = [a, b];

_.reduceRight(fns, _.wrap, function())();


비동기 함수 실행시키는 또 다른 예제.

function asyncFunctionReduce(arr, completeCallback){
  var resArr = [];
  var fns = _.map(arr, function(item){
    return function(next){
      asyncFunction(item, function(kcd){
        resArr.push(kcd);
        next();
      });
    }
  });

  _.reduceRight (fns, _.wrap, function(){
    completeCallback(resArr);
  })();
}

 

find

iteratee의 반환값이 true인 첫번째 값을 반환

내부적으로 some을 호출함. some과 동일 하다고 할 수 있음.

//_.reduceRight(list, iteratee, memo, [context]) var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); => 2


filter

find와는 다르게 true인 값을 리스트로 반환

특화함수 : where

반대함수 : reject

 

//_.filter(list, predicate, [context])

var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });

=> [2, 4, 6] 

 


where

list의 각 value에서 리스트에서 key-value값이 맞는 모든 properties를 반환

//_.where(list, properties)

_.where(listOfPlays, );

=> [,

    ] 

 



findWhere

//_.findWhere(list, properties)

where와 비슷하지만 처음값 하나만을 리턴한다.

 

reject

true면 포함 false면 뺌

filter와 반대
되도록 ES5 filter를 쓰도록하자.

//_.reject(list, predicate, [context])

var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });

=> [1, 3, 5]

 


every

list내 모든게 참이여야 true를 반환 
되도록 ES5 filter를 쓰도록하자.

//_.every(list, [predicate], [context])

_.every([2, 4, 5], function(num) { return num % 2 == 0; });

=> false

 


some

하나라도 조건을 만족하면 true!

//_.some(list, [predicate], [context])

_.some([null, 0, 'yes', false]);

=> true 

 


contains

lis에 해당 value값이 있으면 참 fromIndex를 넣을경우 해당 index에 값이 있어야 참

//_.contains(list, value, [fromIndex])

_.contains([1, 2, 3], 3);

=> true 

 


invoke

list에서 methodName을 정의하면 해당 method를 이용 return값 반환

//_.invoke(list, methodName, *arguments) _.invoke([[5, 1, 7], [3, 2, 1]], 'sort'); => [[1, 5, 7], [1, 2, 3]]

pluck

list에 propery 이름이 동일한 값을 받아 새로운 리스트를 만든다

   맵의 특화 함수..   _.map(function (post){

 return post.id })

   _.pluck('id')

   같음.

 

 

//_.pluck(list, propertyName)

var stooges = [, , ];

_.pluck(stooges, 'name');

=> ["moe", "larry", "curly"]



max

최대값 반환

//_.max(list, [iteratee], [context]) var stooges = [, , ]; _.max(stooges, function(stooge){ return stooge.age; }); => ;

min

최소값 반환

//_.min(list, [iteratee], [context])
var array1 = [92,541,253,3,634,57,6,07,98];
var minResult = _.min(array1,function(item){
return item;
});
console.log("minResult : "+minResult);
//결과>>
//minResult : 3

list가 undefine이거나 빈배열일 경우 Infinity를 반환함


sortBy

sorting 용

//_.sortBy(list, iteratee, [context])
var array1 = [92,541,253,3,634,57,6,07,98];
var sortResult = _.sortBy(array1,function(item){
return item;
});
console.log("sortResult : "+sortResult);
//결과>>(올림차순으로 되네..)
//sortResult : 3,6,7,57,92,98,253,541,634
 var stooges = [, , ]; _.sortBy(stooges, 'name'); => [, , ];

groupBy

리턴값이 같은것끼리 array로 묶음

//_.groupBy(list, iteratee, [context]) _.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); }); => {1: [1.3], 2: [2.1, 2.4]} _.groupBy(['one', 'two', 'three'], 'length'); => {3: ["one", "two"], 5: ["three"]}

리턴값이 undefined 면 그룹의 키값도 undefined 가 됩니다.


const arr = [
  { firstName: "Yi", lastName: "Soonsin" },
  { firstName: "Kang", lastName: "Kamchan" },
  { firstName: "Han", lastName: "Sohee" },
  { firstName: "Han", lastName: "Jungpan" },
];

const res = _.groupBy(arr, function (item) {
  if (item.firstName == "Han"{
    return "한씨";
  }
});

console.log(res);
 
== 결과 ==
{ undefined: [ { firstName: 'Yi', lastName: 'Soonsin' }, { firstName: 'Kang', lastName: 'Kamchan' } ], '한씨': [ { firstName: 'Han', lastName: 'Sohee' }, { firstName: 'Han', lastName: 'Jungpan' } ] }

indexBy

배열들을 index값을 기준으로 mapping

//_.indexBy(list, iteratee, [context])

var stooges = [, , ];

_.indexBy(stooges, 'age');

=> {

  "40": ,

  "50": ,

  "60":

}

 

 

countBy

iteratee의 반환값의 개수를 반환

//_.countBy(list, iteratee, [context]) _.countBy([1, 2, 3, 4, 5], function(num) { return num % 2 == 0 ? 'even': 'odd'; }); => 

suuffle

섞어서 copy list 반환

//_.shuffle(list) _.shuffle([1, 2, 3, 4, 5, 6]); => [4, 1, 6, 3, 5, 2]

sample

랜덤하게 뽑는다.

//_.sample(list, [n]) _.sample([1, 2, 3, 4, 5, 6]); => 4 _.sample([1, 2, 3, 4, 5, 6], 3); => [1, 6, 2] 

toArray

argument 들을 배열로 리턴

//_.toArray(list) (function(){ return _.toArray(arguments).slice(1); })(1, 2, 3, 4); => [2, 3, 4]

list

배열 개수 반환

//_.size(list) _.size(); => 3

partition

array를 두 그룹으로 나눈다 그 후 만족하는 것과 만족하지 않는것을 각각 
어레이로 묶는다.

//_.partition(array, predicate) _.partition([0, 1, 2, 3, 4, 5], isOdd); => [[1, 3, 5], [0, 2, 4]]


Array Functions

first

return first elelment 
n이 있으면 앞에서 n번째

//_.initial(array, [n]) _.first([5, 4, 3, 2, 1]); => 5

initial

뒤에서 n번째

//_.last(array, [n]) _.last([5, 4, 3, 2, 1]); => 1

last

first와 동일하나 뒤에서부터

//_.last(array, [n]) _.last([5, 4, 3, 2, 1]); => 1

rest

index 앞까지 스킵하고 나머지 리턴.

//_.rest(array, [index]) _.rest([5, 4, 3, 2, 1]); => [4, 3, 2, 1]

compact

false,null,0,””빼고 다 반환

//_.compact(array) _.compact([0, 1, false, 2, '', 3]); => [1, 2, 3]

flatter

nesting을 어느 depth던 다 제거한다. shallow를 true로 주면 single level만 
제거한다

//_.flatten(array, [shallow]) _.flatten([1, [2], [3, [[4]]]]); => [1, 2, 3, 4]; _.flatten([1, [2], [3, [[4]]]], true); => [1, 2, 3, [[4]]]; 

without

value값을 제외한 나머지값을 리턴

//_.without(array, *values) _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); => [2, 3, 4]

union

전달 된 모든 배열의 각 개별 요소의 집합을 포함하는 배열을 제공한다.

//_.union(*arrays) _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]); => [1, 2, 3, 101, 10]

intersection

교집합

//_.intersection(*arrays) _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]); => [1, 2]

difference

차집합

//_.difference(array, *others)

_.difference([1, 2, 3, 4, 5], [5, 2, 10]);

=> [1, 3, 4]

 


uniq

중복이 없도록 한 배열을 제공한다. 배열이 이미 정렬되어있으면, 
빠른 알고리즘을 사용할 수있는 옵션이있다.

//_.uniq(array, [isSorted], [iteratee]) _.uniq([1, 2, 1, 4, 1, 3]); => [1, 2, 4, 3]
var ages = [,
,
,
,
,
];
var uniqueres = _.unique(ages, "age");
console.log("uniqueres : "+JSON.stringify(uniqueres));
//결과>>
//uniqueres : [{"age":11,"name":"AA"},{"age":12,"name":"CC"}]

zip

서로 상응하는 값끼리 묶어준다

//_.zip(*arrays) _.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]); => [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]

unzip

zip의 반대개념

//_.unzip(array) _.unzip([["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]); => [['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]] 

object

obj를 array로 변환해준다 단일값이나 key,value 쌍으로 가능

//_.object(list, [values]) _.object(['moe', 'larry', 'curly'], [30, 40, 50]); => _.object([['moe', 30], ['larry', 40], ['curly', 50]]); => 

indexOf

몇번째 value인지 sorting 되어있다면 isSorted 에 true를 주어 더욱 빠르게 검색가능

//_.indexOf(array, value, [isSorted]) _.indexOf([1, 2, 3], 2); => 1

lastIndexOf

indexOf의 reverse 버전

//_.lastIndexOf(array, value, [fromIndex]) _.lastIndexOf([1, 2, 3, 1, 2, 3], 2); => 4

sortedIndex

sorting 되어있는 값을 기준으로 몇번째 인덱스에 넣을 수 있는지 반환

//_.sortedIndex(list, value, [iteratee], [context]) _.sortedIndex([10, 20, 30, 40, 50], 35); => 3 var stooges = [, ]; _.sortedIndex(stooges, , 'age'); => 1

findIndex

indexof와 비슷하나 predicate(true or flase)에서 true된 값을 기준으로 한다

//_.findIndex(array, predicate, [context])

_.findIndex([4, 6, 8, 12], isPrime);

=> -1 // not found

_.findIndex([4, 6, 7, 12], isPrime);

=> 2

 


FindLastIndex

findIndex reverse version

//_.findLastIndex(array, predicate, [context])

var users = [{'id': 1, 'name': 'Bob', 'last': 'Brown'},

             {'id': 2, 'name': 'Ted', 'last': 'White'},

             {'id': 3, 'name': 'Frank', 'last': 'James'},

             {'id': 4, 'name': 'Ted', 'last': 'Jones'}];

_.findLastIndex(users, {

  name: 'Ted'

});

=> 3 

 


range

범위

 //_.range([start], stop, [step])

_.range(10);

=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

_.range(1, 11);

=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

_.range(0, 30, 5);

=> [0, 5, 10, 15, 20, 25]

_.range(0, -10, -1);

=> [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]

_.range(0);

=> []

 


Functional function

bind

바인딩

//_.bind(function, object, *arguments) var func = function(greeting){ return greeting + ': ' + this.name }; func = _.bind(func, , 'hi'); func(); => 'hi: moe'

bindAll

//_.bindAll(object, *methodNames) var buttonView = { label : 'underscore', onClick: function(){ alert('clicked: ' + this.label); }, onHover: function(){ console.log('hovering: ' + this.label); } }; _.bindAll(buttonView, 'onClick', 'onHover'); // When the button is clicked, this.label will have the correct value. jQuery('#underscore_button').on('click', buttonView.onClick);

partial

인자를 하나씩 넣을 수 있다. //_.partial(function, *arguments) var subtract = function(a, b) { return b - a; }; //subtract의 인자 2개 sub5 = _.partial(subtract, 5); //subtract의 첫 인자에 5를 셋팅한 값을 sub5에 넘김 sub5(20); //sub5 = subtract(5,argument) => 15 // Using a placeholder subFrom20 = _.partial(subtract, _, 20); //_로 막아놓기 가능 subFrom20(5); => 15

memoize

결과를 저장하는 것으로, 고비용의 함수를 memoize 화한다.

//_.memoize(function, [hashFunction]) var fibonacci = _.memoize(function(n) { return n < 2 ? n: fibonacci(n - 1) + fibonacci(n - 2); });

delay

시간만큼 딜레이 후 실행시킴

//_.delay(function, wait, *arguments) var log = _.bind(console.log, console); _.delay(log, 1000, 'logged later'); => 'logged later' // Appears after one second.

defer

call stack의 내용이 전부 처리되면 실행시킨다

//_.defer(function, *arguments) _.defer(function(){ alert('deferred'); }); // Returns from the function before the alert runs. 

throttled

호출되면 지정된 시간 내에 최대 1 번만 트리거되는 함수를 돌려 준다.

//_.throttle(function, wait, [options]) var throttled = _.throttle(updatePosition, 100); $(window).scroll(throttled);

debounce

연속 호출되는 한 트리거되지 않는 함수를 돌려준다. 
예를들어 함수가 wiat만큼 기다리는동안 immediate의 return값을 
받을경우 혹은 연속된 호출을 받을경우 호출이 시작된 시점부터 다시 
카운팅 후 실행되게 된다.

//_.debounce(function, wait, [immediate]) var lazyLayout = _.debounce(calculateLayout, 300); $(window).resize(lazyLayout);

once

딱 한번만 실행

//_.once(function) var initialize = _.once(createApplication); initialize(); initialize(); // Application is only created once.

after

n번 호출된 이후에 실행한다.

//_.after(count, function) var renderNotes = _.after(notes.length, render); _.each(notes, function(note) { note.asyncSave(); }); // renderNotes is run once, after all notes have saved.

before

횟수제한

//_.before(count, function) var monthlyMeeting = _.before(3, askForRaise); monthlyMeeting(); monthlyMeeting(); monthlyMeeting(); // the result of any subsequent calls is the same as the second call

wrap

wrap을 씌워준다.

//.wrap(function, wrapper) var hello = function(name) { return "hello: " + name; }; hello = _.wrap(hello, function(func) { return "before, " + func("moe") + ", after"; }); hello(); => 'before, hello: moe, after'

negate

predicate를 0 혹은 1로 반환하는 것같다.

//_.negate(predicate) var isFalsy = _.negate(Boolean); _.find([-2, -1, 0, 1, 2], isFalsy); => 0

compose

함수 목록에서 각각의 함수가 거기에 계속되는 함수의 반환 값을 인수에 취하는 합성 함수를 돌려 준다. 
f(), g(), and h() produces f(g(h())).

//_.compose(*functions) var greet = function(name){ return "hi: " + name; }; var exclaim = function(statement){ return statement.toUpperCase() + "!"; }; var welcome = _.compose(greet, exclaim); welcome('moe'); => hi! moe

 

 

Object Functions

keys

obj의 key 반환

//_.keys(object)

_.keys();

=> ["one", "two", "three"] 

 


allKeys

obj의 모든 inherited properties 출력

//_.allKeys(object) function Stooge(name) { this.name = name; } Stooge.prototype.silly = true; _.allKeys(new Stooge("Moe")); => ["name", "silly"]

values

value 반환

//_.values(object) _.values();  

=> [1, 2, 3] 

 


mapObject

예제를 보자

//_.mapObject(object, iteratee, [context]) _.mapObject(, function(val, key) { return val + 5; });

paris

obj to list

//_.pairs(object) _.pairs(); => [["one", 1], ["two", 2], ["three", 3]]

invert

obj의 key값과 value값을 바꿔준다.

const resEx1 = _.invert({ Moe: "Moses", Larry: "Louis", Curly: "Jerome" });
//결과 : { Moses: 'Moe', Louis: 'Larry', Jerome: 'Curly' }
const resEx2 = _.invert({ Moe: "Moses", Moe2: "Moses" });
// 결과 : { Moses: 'Moe2' }

 

extend

예제 destination에서 source로 값을 복사 하고 desinatio을 리턴 (두 값을 합쳐주는데 같은 필드가 있으면 뒤의 것을 사용한다는 뜻)

_.extend(detination, *srouce)

_.extend(, );

=>  

 

 

pick

keys들로 필터링 해준다.

_.pick(object, *keys)
_.pick(,
'name', 'age','con');
//결과
//

 

 
var res = _.pick({ name: "moe", age: 50, userid: "moe1", con: "Germany" }, "fullname", "age", "con");
//결과 : { age: 50, con: 'Germany' }

=> key가 없으면 반환값이 포함되지 않는다.

=> 반대 동작(blacklist)는 omit를 사용하면 된다.

 

 

 

chain

chain 사용.
 
1
{
Mumbai: [ { origin: 'Mumbai', destination: 'Chennai' },
{ origin: 'Mumbai', destination: 'Delhi' } ],

Pune: [ { origin: 'Pune', destination: 'Brahmapur' } ]
}

var result = _.chain(data)
.groupBy('origin')
.mapObject(group => _.pluck(group, 'destination'))
.value()
2
 
3