Underscore 의 _.each
v1부터 현재까지 코드가 어떻게 변해왔는지 확인해봅니다.
[~v0.1.0]
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
window._ = {
each : function(obj, iterator, context) {
var index = 0;
try {
if (obj.forEach) {
obj.forEach(iterator, context);
} else if (obj.length) {
for (var i=0; i<obj.length; i++) iterator.call(context, obj[i], i);
} else if (obj.each) {
obj.each(function(value) { iterator.call(context, value, index++); });
} else {
var i = 0;
for (var key in obj) {
var value = obj[key], pair = [key, value];
pair.key = key;
pair.value = value;
iterator.call(context, pair, i++);
}
}
} catch(e) {
if (e != '__break__') throw e;
}
return obj;
}
}
1. window객체에 _.each function을 직접 할당해서 사용하고 있습니다.
2. 데이터가 배열, 기본 배열이 아닌 리스트 (ex. 문자열, jQuery), 객체인 경우 loop가 적용되고 있습니다.
(obj.each는 뭐지?)
1 | window._ = { |
[~v0.3.1]
1 | _.each = function(obj, iterator, context) { |
- v2 버전에서 window객체가 없을 때도 사용되도록 전체 구조가 변경되었습니다.
- 들어오는 데이터가 객체일 경우 프로퍼티 값이 있는지 확인하는 코드가 추가 되었습니다.
- iterator.call의 argument값이 달라졌습니다. 하나의 obj가 아니라 각각의 값을 넣습니다.
[~v0.4]
1 | var breaker = typeof StopIteration !== 'undefined' ? StopIteration : '__break__'; |
v0.4.1
- obj.each를 검사하는 코드가 제거되었습니다.
v0.4.3
- 에러 체크 방식이 변경되었습니다.
StopIteration를 체크하는 코드가 있었는데 현재 StopIteration는 Deprecated 되었습니다.
v0.4.7
1. obj Loop시 _.keys function이 추가되었습니다.
2. for in -> for 문으로 변경되었습니다.
[~v0.5]
1 | _.each = function(obj, iterator, context) { |
v0.5.1
- obj.length -> _.isArray(obj) || _.isArguments(obj)로 변경되었습니다.
v0.5.8
- 다시 _.isNUmber(obj.length)로 변경되었습니다.
[~v0.6.0]
1 | var each = _.forEach = function(obj, iterator, context) { |
- each가 foreach라는 이름도 갖게 되었습니다.
- 기본 배열인지 확인하는 비교문이 수정되었습니다.(nativeForEach = ArrayProto.forEach)
- 들어오는 obj가 객체인 경우 loop 가 다시 for에서 for in으로 변경되었습니다.
내부 loop에서 hasOwnProperty를 사용해서 property확인을 합니다.
[~v1.1.4]
1 | var each = _.each = _.forEach = function(obj, iterator, context) { |
- try catch문을 제거되었습니다.
- null check를 추가되습니다.
[~v1.1.7]
1 | var each = _.each = _.forEach = function(obj, iterator, context) { |
- _.isNumber(obj.length)가 obj.length === +obj.length으로 변경되었습니다.
[~v1.3.1]
1 | var each = _.each = _.forEach = function(obj, iterator, context) { |
- hasOwnProperty.call(obj, key)이 _.has()로 수정되었습니다.
[~v1.4.2]
1 | var each = _.each = _.forEach = function(obj, iterator, context) { |
- obj.length === +obj.length에서 “i in obj”가 제거되습니다.
[~v1.5.2]
1 | var each = _.each = _.forEach = function(obj, iterator, context) { |
- obj loop방식도 또 변경되었고, l의 네이밍이 length로 변경되었습니다.
[~v1.7.0]
1 | _.each = _.forEach = function(obj, iteratee, context) { |
- interator.call 함수가 전역으로 나누어졌습니다.
[~v1.8.0]
1 | _.each = _.forEach = function(obj, iteratee, context) { |
- createCallback -> optimizeCb 으로 function이름이 변경되었습니다.
- null 체크가 삭제되었습니다.
- v0.3.1에서 “(Object.prototype.hasOwnProperty.call(obj, key)”를 for문과 같이 쓰이는 구조가 처음보는 익혀둬야 할것 같다.
- 점진적으로 여러 예외경우를 추가하면서 try catch 을 제거하는 방식도 괜찮은 방식이인것 같다.
- for문과 for in 문에 반복적으로 교체되고 있다. 장단점을 확실히 아는게 좋을것 같다.
- 확실히 최종보전부터 보면 이해가 안되지만 처음버전부터 보면 히스토리를 알게되서 이해가 더 알기 좋다.