donaricano-btn

 한번만 실행되는 함수 _.once()


1. _.once()

- 고차함수로 함수를 한 번만 실행 시킨다

1) 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
_.once = function(func){
  var flag, result;
  return function(){
   if(flag){return result};
   flag = true;
   return result = func.apply(this, argument);
 }
}
 
var hi = _.once(function(){console.log('hi')});
 
hi(); //hi
hi();//실행안됨

블로그 이미지

리딩리드

,
donaricano-btn

_.identity(), _.values() 구현


1. _,identity()

- 쓸모없어 보이는 함수

- 받은 파라미터를 바로 반환 한다.

- 단독 사용에 의미가 없지만 여러 함수들과 합쳐져 의미를 만든다.

1) 구현

1
2
3
_.identity = function(v){
  return v;
}


2. _.values()

- 객체의 값만을 array 형태로 출력한다.

- _,map(), _.identity() 가 사용되었다

1) 구현

1
2
3
4
5
6
_.values = function(list){
   return _.map(list, _.identity);
}
 
console.log(_values({id:5, name:'je'});
//[5,'je']
 


3. _.keys()

- values의 반대로 객체의 키 값만을 배열로 출력한다

1) 구현

1
2
3
4
5
6
7
8
9
_args1 = function(a,b){
  return b;
}
 
_.args0 = _,identity;
 
_,keys = function(list){
  return _.map(list, _.args1);
}
 

블로그 이미지

리딩리드

,
donaricano-btn

_,map(), getLength(), isArrayLike() 구현


1. getLength()

- data.length 값을 측정할 때 'length' of undefined 라는 오류를 피할 수 있다.

1) 일반적인 상황 에러

1
2
3
4
5
6
function fun(data){
  for(var i = 0; i<data.length; i++){}
}
 
fun(undefined);
//Cannot read property 'length' of undefined

- 주석과 같은 아래 발생

2) getLength() 함수 적용

1
2
3
4
5
6
7
8
9
10
11
12
13
function getLength(list){
  return list == null ? undefined : list.length;
}
 
function getLength(list){
  return list == null ? void 0 : list.length;
}
 
function fun(data){
  for(var i = 0; i<getLength(data); i++){}
}
 
// 0<undefinded 이므로 false 반환
 

- false를 반환 하므로 for문이 동작하지 않는다.


2. isArrayLike()

- 자바스크립트의 객체는 4가지가 있다. [], {}, arguments, ArrayLike 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1. []
var array = [1,2];
 
2. {}
var object = {name:'kyle', age : 25}
 
3. arguments
var arguments = function(){
  return arguments;
}(1,2,3)
 
4. ArrayLike
var $div = $('div');
var object = { length:3}
object[0] = 1, object[1]=2
var string = "hi"
 

- ArrayLike 를 판단한다

1
2
3
4
5
6
7
var MAX_ARRAY_INDEX = Math.pow(2,53) -1
var isArrayLike = function(list){
  var length = getLength(list);
  return typeof length == 'numbe'r && length >= 0 && length <= MAX_ARRAY_INDEX;
};
 
//TRUE OR FALSE
 


3. _.map()

- underscore.js 의 map()를 구현한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
_.map = function(data, iteratee){
     
    var new_list = [];
    if(isArrayLike){
        for(var i = 0; i<data.length; i++){
            new_list.push(iteratee(data[i], i, data));
        }
    }else{
        for(var key in data){
            if(data.hasOwnProperty(key)){
                new_list.push(iteratee(data[key],key, data));
            }
        }
    }
    return new_list;
     
}
 
_.map([1,2,3], function(v){
    return v * 2
});
//[2,4,6]
_.map({a:3, b:2, c:1}, function(v){
    return v * 2
});
//[6,4,2]
 

- array 계열인지 object 계열인지 판별하여 for 혹은 for in 을 구현한다.

블로그 이미지

리딩리드

,
donaricano-btn

함수형에서 for 와 if 의 변화


1. for에서 filter로 if에서 predicate로

1) 기존 문장

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var users = [
    {id :1, name :'ID', age:32},
    {id :2, name :'ha', age:30},
    {id :3, name :'bj', age:29},
]
 
//30살 이하의 데이터를 추출하여 새로운 배열에 넣는다
var temp_user = [];
for(var i = 0, len = users.length; i<len; i++){
    if(users[i].age<30){
        temp_user.push(users[i]);
    }
}
console.log(temp_user.length);

2) filter 함수로 변환

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var users = [
    {id :1, name :'ID', age:32},
    {id :2, name :'ha', age:30},
    {id :3, name :'bj', age:29},
]
 
function filter(list, predicate){
    var new_list = [];
    for(var i = 0, len = list.length; i<len; i++){
        if(predicate(list[i])){
            new_list.push(list[i]);
        }
    }
    return new_list;
}
 
var users_under_30 = filter(users, function(user) { return user.age < 30 });
var users_over_30 = filter(users, function(user){return user.age > 30});
console.log(users_under_30.length);
 

- 새로운 배열을 생성하여 반환한다.

- predicate 함수를 이용하여 원하는 반환 값을 얻는다.


2. 중복 코드를 map 함수로 제거한다

1) 기존 문장

1
2
3
4
5
var ages = [];
for(var i = 0, len = temp_user.length; i<len; i++){
    ages.push(temp_user[i].age);
}
console.log(ages);
 

- 새로 만든 배열에서 이름을 추출한다.

2) map 함수로 변환

1
2
3
4
5
6
7
8
9
10
11
function map(list, iteratee){
    var new_list = [];
    for(var i=0, len = list.length; i<len; i++){
        new_list.push(iteratee(list[i]))
    }
    return new_list;
}
 
var ages = map(users_under_30, function(user){return user.age});
var name = map(filter(users, function(user) { return user.age < 30 }), function(user){return user.name});
console.log(ages);
 

- 코드가 더욱 단순해 졌다. 또한 함수를 합쳐서 실행결과로 바로 실행할 수 있다.


3. 클로저를 이용한 map 함수 줄이기

1) 클로저 함수 패턴

1
2
3
4
5
6
7
8
9
function bvalue(key){
    return function(obj){
        return obj[key];
    }
}
 
var b = bvalue('b');
console.log(b({a:'hi',b:'hello'}));
console.log(bvalue('a')({a:'hi',b:'hello'}));
 

2) filter, map, bvalue 

1
var name = map(filter(users, function(user) { return user.age < 30 }), bvalue('name'));
 

- 더욱 간결해 졌다.

블로그 이미지

리딩리드

,