Backbone.js를 익히기 전에 Underscore에 대해서 알아보자.
1) Underscore
- Functional Programming을 위한 자바스크립트 유틸리티 라이브러리
- 80 개의 펑션을 가지고 있다
- var _ 변수 사용
2) 테스트 돌려보기
- GitHub에서 다운로드 : git clone https://github.com/documentcloud/underscore.git
- package.json 내역
{
"name" : "underscore","description" : "JavaScript's functional programming helper library.","homepage" : "http://underscorejs.org","keywords" : ["util", "functional", "server", "client", "browser"],"author" : "Jeremy Ashkenas <jeremy@documentcloud.org>","repository" : {"type": "git", "url": "git://github.com/documentcloud/underscore.git"},"main" : "underscore.js","version" : "1.4.4","devDependencies": {"phantomjs": "1.8.1-3"},"scripts": {"test": "phantomjs test/vendor/runner.js test/index.html?noglobals=true"}}
- scripts 의 test 에서 phantomjs 사용함 : 참조에서 phantomjs를 설치한다 (웹브라우져 없이 테스트시 많이 사용)
+ phantomjs 를 이용한 테스트 코드 작성 연구에 도움이 되겠다
+ 테스트 코드는 underscore/test 디렉토리에 존재함
$ npm test
> underscore@1.4.4 test /Users/nulpulum/git-repositories/underscore
> phantomjs test/vendor/runner.js test/index.html?noglobals=true
2013-03-11 13:58:26.100 phantomjs[32711:f07] *** WARNING: Method userSpaceScaleFactor in class NSView is deprecated on 10.7 and later. It should not be used in new applications. Use convertRectToBacking: instead.
Took 2309ms to run 588 tests. 588 passed, 0 failed.
3) Collection Functions
- 테스트 코드
+ 모듈 설치하기 : npm install underscore
var _ = require('underscore'); | |
console.log('-------each'); | |
_.each([1,2,3], console.log); | |
console.log('-------map'); | |
_.map([1,2,3], function(num){ console.log( num*3 );}); | |
console.log('-------reduce'); | |
var sum = _.reduce([1,2,3], function(memo, num) { | |
return memo+num; | |
}, 0); | |
console.log(sum); | |
console.log('-------find : display first value'); | |
var even = _.find([1,2,3,4,5,6], function(num){ | |
return num % 2 ==0; | |
}); | |
console.log(even); | |
console.log('-------filter'); | |
even = _.filter([1,2,3,4,5,6], function(num){ | |
return num % 2 ==0; | |
}); | |
console.log(even); | |
console.log('-------reject'); | |
odds = _.reject([1,2,3,4,5,6], function(num){ | |
return num % 2 ==0; | |
}); | |
console.log(odds); | |
console.log('-------every'); | |
var result = _.every([true, 1, null, 'yes'], _.identity); | |
console.log(result); | |
console.log('-------some'); | |
result = _.some([true, 1, null, 'yes'], _.identity); | |
console.log(result); | |
console.log('-------contains'); | |
result = _.contains([1,2,3], 3); | |
console.log(result); | |
console.log('-------invoke'); | |
result = _.invoke([[5,1,7], [3,2,1]], 'sort'); | |
console.log(result); | |
console.log('-------pluck'); | |
var dowon = [{name: 'dowon', age:22}, {name: 'haha', age:37}, {name: 'youngsik', age:99}]; | |
result = _.pluck(dowon, 'name'); | |
console.log(result); | |
console.log('-------max'); | |
dowon = [{name: 'dowon', age:22}, {name: 'haha', age:37}, {name: 'youngsik', age:99}]; | |
result = _.max(dowon, function(dw){ return dw.age}); | |
console.log(result); | |
console.log('-------min'); | |
dowon = [10,3,4,5,1000]; | |
result = _.min(dowon); | |
console.log(result); | |
console.log('-------groupBy'); | |
result = _.groupBy([1.3, 2.1, 2.4, 1.9], function(num){ return Math.floor(num);}); | |
console.log(result); | |
console.log('-------countBy'); | |
result = _.countBy([1,2,3,4,5], function(num){ return num%2==0? 'even':'odd';}); | |
console.log(result); | |
console.log('-------toArray'); | |
result = (function(){ return _.toArray(arguments).slice(1); })(1,2,3,4); | |
console.log(result); | |
console.log('-------size'); | |
result = _.size({one:1, hi:33, name:'dowon'}); | |
console.log(result); |
- 테스트 결과
//////////////////////////////////////
// 샘플 코드 짜고 node 로 결과 확인하기
$ node collection.js
-------each : 개별 요소를 지정한 function에서 수행
1 0 [ 1, 2, 3 ]
2 1 [ 1, 2, 3 ]
3 2 [ 1, 2, 3 ]
-------map : 각 요소를 지정한 callback에서 수행
3
6
9
-------reduce : 리듀싱
6
-------find : callback에서 찾는 즉시 break
2
-------filter : callback에 매칭되는 것만
[ 2, 4, 6 ]
-------reject : callback에 매칭되지 않는 것만
[ 1, 3, 5 ]
-------every : 모두가 지정한 값일 경우 참
false
-------some : 하나라도 지정한 값일 경우 참
true
-------contains : 포함하면 참
true
-------invoke : 펑션 호출
[ [ 1, 5, 7 ], [ 1, 2, 3 ] ]
-------pluck : 지정한 프러퍼티만 뽑아냄
[ 'dowon', 'haha', 'youngsik' ]
-------max : 지정한 프로퍼티중 최대인 것
{ name: 'youngsik', age: 99 }
-------min : 지정한 플터피중 최소인 것
3
-------groupBy : 그룹핑
{ '1': [ 1.3, 1.9 ], '2': [ 2.1, 2.4 ] }
-------countBy : callback 계산된 그룹핑 건수
{ odd: 3, even: 2 }
-------toArray : 배열 리턴
[ 2, 3, 4 ]
-------size : 크기
3
** 기타 몇가지 테스트 안한 API : where, findWhere, sortBy, shuffle 등
4) Array Functions
- 테스트 코드
var _ = require('underscore'); | |
console.log('------first'); | |
var result = _.first([5,4,3,2,1]); | |
console.log(result); | |
console.log('------initial'); | |
var result = _.initial([5,4,3,2,1]); | |
console.log(result); | |
console.log('------last'); | |
var result = _.last([5,4,3,2,1]); | |
console.log(result); | |
console.log('------rest'); | |
var result = _.rest([5,4,3,2,1]); | |
console.log(result); | |
console.log('------compact'); | |
var result = _.compact([0,4,false,2,'',null]); | |
console.log(result); | |
console.log('------flatten'); | |
var result = _.flatten([1, [2], [3], [[4]]]); | |
console.log(result); | |
console.log('------without'); | |
var result = _.without([1,2,1,0,3,4,2], 0,2); | |
console.log(result); | |
console.log('------union'); | |
var result = _.union([1,2,3], [101,2,1,11], [2,1]); | |
console.log(result); | |
console.log('------intersection'); | |
var result = _.intersection([1,2,3], [101,2,1,11], [2,1]); | |
console.log(result); | |
console.log('------uniq'); | |
var result = _.uniq([1,2,3,1,2,4,5,3]); | |
console.log(result); | |
console.log('------zip'); | |
var result = _.zip(['a','b','c'],[1,2,4],[true,false, true]); | |
console.log(result); | |
console.log('------object'); | |
var result = _.object(['a','b','c'],[1,2,4],[true,false, true]); | |
console.log(result); | |
console.log('------indexOf'); | |
var result = _.indexOf([1,2,3], 3); | |
console.log(result); | |
console.log('------lastIndexOf'); | |
var result = _.lastIndexOf([1,2,3,1,2,3], 2); | |
console.log(result); | |
console.log('------sortedIndex'); | |
var result = _.sortedIndex([1,2,3,4], 2.5); | |
console.log(result); | |
console.log('------range'); | |
var result = _.range(4); | |
console.log(result); |
- 테스트 결과
////////////////////////////////////////////////////////////////
// 테스트 코드를 작성하면서 nodemon 을 통하여 결과값을 확인한다
$ nodemon array.js
------first : 배열 첫번째 요소
5
------initial : 마지막 요소 제외한 배열
[ 5, 4, 3, 2 ]
------last : 배열 마지막 요소
1
------rest : 첫번째 요소 제외한 요소
[ 4, 3, 2, 1 ]
------compact : '' 0 false null등을 제외한 요소만
[ 4, 2 ]
------flatten : 1차원 배열로
[ 1, 2, 3, 4 ]
------without : 지정한 요소를 제거한 배열
[ 1, 1, 3, 4 ]
------union : 중복 제거
[ 1, 2, 3, 101, 11 ]
------intersection : 서로 중복되는 것만
[ 1, 2 ]
------uniq : 유니크한 것만
[ 1, 2, 3, 4, 5 ]
------zip : 각 배열의 요소끼리 2차원배열
[ [ 'a', 1, true ], [ 'b', 2, false ], [ 'c', 4, true ] ]
------object : 2개 배열의 요소를 javascript obejct형식의 {key:value}로 변환
{ a: 1, b: 2, c: 4 }
------indexOf : 앞에서 부터 지정한 위치
2
------lastIndexOf : 뒤에서 부터 지정한 위치
4
------sortedIndex : 지정한 값이 들어갈 위치
2
------range : 지정한 길이 만큼 배열 만들기
[ 0, 1, 2, 3 ]
5) Object Functions
- 테스트 코드
_ = require 'underscore' | |
console.log '--------keys' | |
result = _.keys {one:1, two:2, three:3} | |
console.log result | |
console.log '--------values' | |
result = _.values {one:1, two:2, three:3} | |
console.log result | |
console.log '--------pairs' | |
result = _.pairs {one:1, two:2, three:3} | |
console.log result | |
console.log '--------invert' | |
result = _.invert {one:1, two:2, three:3} | |
console.log result | |
console.log '--------functions' | |
result = _.functions _ | |
console.log result | |
console.log '--------extend' | |
result = _.extend {name:'dowon'}, {age:33} | |
console.log result | |
console.log '--------pick' | |
result = _.pick {name:'dowon', age:33}, 'age' | |
console.log result | |
console.log '--------omit' | |
result = _.omit {name:'dowon', age:33}, 'age' | |
console.log result | |
console.log '--------defaults' | |
iceCream = {flavor:'chocolate'} | |
result = _.defaults iceCream, {flavor:'oye', orange: 'lots'} | |
console.log result | |
console.log '--------clone' | |
result = _.clone {name:'dowon', age:33} | |
console.log result | |
console.log '--------tap' | |
_.chain([1,2,3,400]) | |
.filter (num) -> | |
num % 2 == 0 | |
.tap(console.log) | |
.map (num) -> | |
num * num | |
.value | |
console.log '--------has' | |
result = _.has {name:'dowon', age:33}, 'age' | |
console.log result |
- 테스트 결과
//////////////////////////////////////////////////////
// coffee-script 로 작성하고 compile과 watch 옵션을 준다
$ coffee --compile --watch object.coffee
//////////////////////////////////////////////////////
// nodemon 으로 컴파일된 object.js 를 모니터링한다
$ nodemon object.js
11 Mar 16:40:06 - [nodemon] app crashed - waiting for file changes before starting...
11 Mar 16:40:14 - [nodemon] restarting due to changes...
11 Mar 16:40:14 - [nodemon] /Users/nulpulum/development/underscore/test/object.js
11 Mar 16:40:14 - [nodemon] starting `node object.js`
--------keys : 오브젝트의 키만
[ 'one', 'two', 'three' ]
--------values : 오브젝트의 값만
[ 1, 2, 3 ]
--------pairs : 각 오브젝트를 key:value 형태로
[ [ 'one', 1 ], [ 'two', 2 ], [ 'three', 3 ] ]
--------invert : key:value를 거꾸로
{ '1': 'one', '2': 'two', '3': 'three' }
--------functions : 객체의 모든 펑션
[ '_',
'after',
'all',
'any',
'bind',
'bindAll',
'chain',
'clone',
'collect',
'compact',
'compose',
'contains',
'countBy',
'debounce',
'defaults',
'defer',
'delay',
'detect',
'difference',
'drop',
'each',
'escape',
'every',
'extend',
'filter',
'find',
'findWhere',
'first',
'flatten',
'foldl',
'foldr',
'forEach',
'functions',
'groupBy',
'has',
'head',
'identity',
'include',
'indexOf',
'initial',
'inject',
'intersection',
'invert',
'invoke',
'isArguments',
'isArray',
'isBoolean',
'isDate',
'isElement',
'isEmpty',
'isEqual',
'isFinite',
'isFunction',
'isNaN',
'isNull',
'isNumber',
'isObject',
'isRegExp',
'isString',
'isUndefined',
'keys',
'last',
'lastIndexOf',
'map',
'max',
'memoize',
'methods',
'min',
'mixin',
'noConflict',
'object',
'omit',
'once',
'pairs',
'partial',
'pick',
'pluck',
'random',
'range',
'reduce',
'reduceRight',
'reject',
'rest',
'result',
'select',
'shuffle',
'size',
'some',
'sortBy',
'sortedIndex',
'tail',
'take',
'tap',
'template',
'throttle',
'times',
'toArray',
'unescape',
'union',
'uniq',
'unique',
'uniqueId',
'values',
'where',
'without',
'wrap',
'zip' ]
--------extend : 두객체를 합침
{ name: 'dowon', age: 33 }
--------pick : 원하는 것만 끄집어 냄
{ age: 33 }
--------omit : 원하는 것을 삭제함
{ name: 'dowon' }
--------defaults : 기본 값으로 대체
{ flavor: 'chocolate', orange: 'lots' }
--------clone : 객체 복제하기
{ name: 'dowon', age: 33 }
--------tap : 오브젝트 필터링시에 사용
[ 2, 400 ]
--------has : 키가 존재하는지 체크
true
** 그외 is** 관련 펑션이 존재함 (true/false 결과 리턴)
6) Utility Functions
- 테스트 코드
_ = require 'underscore' | |
console.log '------noConflict' | |
result = _.noConflict | |
console.log result | |
console.log '------identity' | |
dowon = {name : 'dowon'} | |
result = _.identity dowon | |
console.log result | |
console.log '------times' | |
result = _(3).times (n) -> | |
console.log n | |
console.log '------random' | |
result = _.random 0, 100 | |
console.log result | |
console.log '------mixin' | |
_.mixin | |
dowon : (string) -> | |
return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase() | |
result = _('youngsik').dowon() | |
console.log result | |
console.log '------uniqueId' | |
result = _.uniqueId 'dowon_' | |
console.log result | |
console.log '------escape' | |
result = _.escape 'dowon & young > hi < ' | |
console.log result | |
console.log '------unescape' | |
result = _.unescape 'dowon & young > hi <' | |
console.log result | |
console.log '------result' | |
obj = { dowon: 'hi', age: 33} | |
result = _.result obj, 'dowon' | |
console.log result | |
console.log '------template' | |
compiled = _.template "hello: <%= name %>" | |
result = compiled {name: 'dowon'} | |
console.log result | |
console.log '------chain' | |
dowon = [{name:'dowon', age:33}, {name:'youngsik', age:22}, {name:'yuyu', age:27}] | |
youngest = _.chain(dowon) | |
.sortBy (dowon) -> | |
return dowon.age | |
.map (dowon) -> | |
return dowon.name + ' is ' + dowon.age | |
.first() | |
.value() | |
console.log youngest |
- 테스트 결과
$ coffee --compile --watch utility.coffee
$ nodemon utility.js
1 Mar 17:07:19 - [nodemon] clean exit - waiting for changes before restart
11 Mar 17:08:06 - [nodemon] restarting due to changes...
11 Mar 17:08:06 - [nodemon] /Users/nulpulum/development/underscore/test/utility.js
11 Mar 17:08:06 - [nodemon] starting `node utility.js`
------noConflict : _ 언더바가 다른 모듈과 쫑나면 변경가능
[Function]
------identity : 복사
{ name: 'dowon' }
------times : 횟수만큼 수행
0
1
2
------random : min~max 사이값 랜덤 생성
10
------mixin : 모듈에 펑션을 확장시킴
Youngsik
------uniqueId : 유니크 아이디를 만들어 줌
dowon_1
------escape
dowon & young > hi <
------unescape
dowon & young > hi <
------result : 지정된 키의 값 반환
hi
------template : 템플릿 엔진 <% ... %> 기본, {{ ... }} 등으로 변경가능
hello: dowon
------chain : 객첵를 여러 메소드에 걸쳐서 수행하고 싶을 경우 최초에 한번에 넣는다
youngsik is 22
// 1) 과 2)는 동일한 표현이다
1) _.map([1, 2, 3], function(n){ return n * 2; });
2) _([1, 2, 3]).map(function(n){ return n * 2; });
<참조>
- package.json의 test 스크립트 구동하기 (Testing)
'Backbone.js' 카테고리의 다른 글
[Backbone.js] 서점 샘플 응용하기 - 01 (0) | 2013.03.15 |
---|---|
[Backbone.js] 큰 규모의 SPA 개발을 위한 준비 (0) | 2013.03.12 |
[Backbone.js] 배우는 방법 (2) | 2013.02.20 |
[Backbone.js] 기본 개념 잡기 (0) | 2013.01.10 |
[Backbone.js] MVC Framework 카테고리 (0) | 2012.12.29 |